Android设计模式之单例模式
作者:网络转载 发布时间:[ 2016/8/2 14:18:29 ] 推荐标签:设计模式
概述
单例模式是应用广的模式之一,在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个全局对象,这样有利于我们协调系统整体的行为。如在一个应用中,应该只有一个ImageLoader实例,这个ImageLoader中又含有线程池、缓存系统、网络请求等,很消耗资源。因此不应该让它构造多个实例。这样不能自由构造对象的情况,是单例模式的使用场景。
定义
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
使用场景
确保某个类有且只要一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源,这时要考虑使用单例模式。
UML类图
单例模式的UML类图如下:
角色介绍:
· Client:高层客户端
· Singleton:单例类
实现单例模式主要有以下几个关键点:
· 构造函数不对外开放,一般为private;
· 通过一个静态方法或者枚举返回单例类对象;
· 确保单例类的对象有且只有一个,尤其是在多线程环境下;
· 确保单例类对象在反序列化时不会重新构建对象;
单例模式中实现比较困难的是在多线程环境下构造单例类的对象有且只有一个。
简单示例
单例模式在设计模式中是结构比较简单的,只有一个单例类,没有其他层次结构和抽象。该模式需要确保该类只能生成一个对象,通常是该类需要消耗较多的资源或者没有对个实例的情况。例如一个公司只有一个CEO、一个应用只有一个Application对象等。
下面以公司里的CEO为例来简单演示一下,一个公司可以有多个VP、无数个员工,但只有一个CEO,代码如下:
/**
*
* 普通员工
*
*/
public class Staff {
public void work() {
//干活
}
}
//副总裁
public class VP extends Staff {
@Override
public void work() {
// 管理下面的经理
}
}
//CEO,饿汉式单例
public class CEO extends Staff {
private static final CEO mCEO = new CEO();
private CEO() {
}
//公有的静态函数,对外暴露获取单例对象的接口
public static CEO getCeo() {
return mCEO;
}
@Override
public void work() {
// 管理VP
}
}
//公司类
public class Company {
private List<Staff> mStaffs = new ArrayList<Staff>();
public void addStaff(Staff staff) {
mStaffs.add(staff);
}
public void showStaffs() {
for(Staff staff : mStaffs) {
System.out.println("Obj: " + staff.toString());
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Company company = new Company();
//CEO对象只能通过getCeo获取
Staff ceo1 = CEO.getCeo();
Staff ceo2 = CEO.getCeo();
company.addStaff(ceo1);
company.addStaff(ceo2);
Staff vp1 = new VP();
Staff vp2 = new VP();
company.addStaff(vp1);
company.addStaff(vp2);
Staff staff1 = new Staff();
Staff staff2 = new Staff();
company.addStaff(staff1);
company.addStaff(staff2);
company.showStaffs();
}
运行输出结果如下:
Obj: com.liuguoquan.design.single.CEO@15db9742
Obj: com.liuguoquan.design.single.CEO@15db9742
Obj: com.liuguoquan.design.single.VP@6d06d69c
Obj: com.liuguoquan.design.single.VP@7852e922
Obj: com.liuguoquan.design.single.Staff@4e25154f
Obj: com.liuguoquan.design.single.Staff@70dea4e
从上面代码可以看出,CEO类不能通过new的形式构造函数,只能通过CEO.getCeo()方法来获取,而这个CEO对象是静态对象,并且在声明的时候已经初始化,这保证类CEO对象的性。
从输出结果中可以看出,CEO两次输出的CEO对象的地址都一样,说明是同一个CEO对象;而VP、Staff等类型的对象都是不同的。
实现方式
饿汉式
饿汉式模式是在声明静态对象时已经初始化,这种方式简单粗暴,如果单例对象初始化非常快,而且占用内存小的时候这种方式是比较适合的,可以直接在应用启动时加载初始化。实现如下:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
懒汉式
懒汉模式是声明一个静态对象,并且在用户第一次调用getInstance时进行初始化。
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
getInstance方法中添加了Synchronized关键字,也是同步类synchronized关键字包含的代码块,这是上面所说的在多线程中保证单例对象性的手段。但是仍存在一个问题,即使instance已经初始化,每次调用getInstance方法都会进行同步,这样会消耗不必要的资源,这也是懒汉式存在的大问题。
懒汉单例模式的优点是只有在使用时才会被实例化,在一定程度上节约了资源,缺点是第一次加载时需要及时进行实例化,反应稍慢,大问题是每次调用geInstance都进行同步,造成不必要的同步开销,这样模式一般不建议使用。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11