Android 应用最广泛的模式——单例模式

● 单例模式介绍

单例模式是应用最广的模式之一,也可能是很多初级工程师唯一会使用的设计模式。在应用这个模式时,代理对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个全局对象,这样又利于我们协调系统整体的行为。如在一个应用中,应该只有一个ImageLoader实例,这ImageLoader中又含有线程池、缓存系统、网络请求等。很消化资源,因此,没有理由让它构造多个实例。这种不能自由构造对象的情况,就是单例模式的使用场景。

● 单例模式的定义

确保某一个类只有一个实例,而且自行实例化并像这个系统提供这个实例。

● 单例模式的使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源,这时就要考虑单例模式。

● 单例模式UML类图

Android 应用最广泛的模式——单例模式_第1张图片

角色介绍:

(1)Client——高层客户端;

(2)Singlet——单例类。

实现单例模式主要如下几个关键点:

(1)构造函数不对外开放,一般为Pirvate;

(2)通过一个静态方法或者枚举返回单例类对象;

(3)确保单例类的对象有且只有一个,尤其在多线程环境下;

(4)确保单例类对象在反序列化时不会重新构建对象。

通过见单例类的构造函数私有化,使得客户端代码不能通过new的形式手动构建单例类的对象。单例类会暴露一个公有的静态方法,客户端需要调用这个静态方法获取到单例类的唯一对象,在获取这个单例对象的过程中需要确保线程安全,即在多线程环境下构造单例类的对象也是有且只有一个,这也是单例模式实现中比较困难的地方。

● 单例模式的简单示例

单例模式是设计模式中比较简单的,只有一个单例类,没有其他的层次结构与抽象。该模式需要确保该类只能生成一个对象,通常是该类需要消耗较多的资源或者没有多个实现的情况。例如一个公司只有一个CEO、一个应用只有一个Appliacton对象等。下面以公司里的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 ArrayList allStaffs = new ArrayList<>();
	public void addStaff(Staff per) {
		allStaffs.add(per);
	}
	public void showAllstffs() {
		for (Staff per : allStaffs) {
			System.out.println("obj : "+per.toString());
		}
	}

}

	public static void main(String[] args) {
		Company cp = new Company();
		Staff ceo1 = CEO.getCeo();
		Staff ce02 = CEO.getCeo();
		cp.addStaff(ceo1);
		cp.addStaff(ce02);
		//通过new 创建VP对象
		Staff vp1 = new VP();
		Staff vp2 = new VP();
		//通过new 来创建Staff对象
		Staff staff1 = new Staff();
		Staff staff2 = new Staff();
		Staff staff3 = new Staff();
		cp.addStaff(vp1);
		cp.addStaff(vp2);
		cp.addStaff(staff1);
		cp.addStaff(staff2);
		cp.addStaff(staff3);
		cp.showAllstffs();
	}

输出结果如下:

obj : text.CEO@7852e922
obj : text.CEO@7852e922
obj : text.VP@4e25154f
obj : text.VP@70dea4e
obj : text.Staff@5c647e05
obj : text.Staff@33909752
obj : text.Staff@55f96302

从上述代码中可以看到,CEO类不能通过new的形式构建对象,只能通过CEO.getCEO()函数来获取,而这个CEO对象是静态对象,并且在声明的时候就已经初始化,这就保证了CEO对象的唯一性。从输出结果中发现,CEO两次输出的CEO对象都是一样的,而VP、Staff等类型的对象都是不同的。这个实现的核心在于将CEO类的构造方法私有化,使得外部程序不能通过构造函数来构造CEO对象,而CEO类通过一个静态方法返回一个静态对象。

你可能感兴趣的:(单例)