【设计模式】之单例模式(Singleton)
单例模式的定义为:保证一个类只有一个实例,并且提供一个全局的访问入口。
Ensure a class only has one instance, and provide a global point of access it.
虽然说,单例模式在所有的模式当中算是比较简单的一个,但是如果牵扯到线程安全问题,似乎没有那么简单。
本文参考《Head First》和《Design Patterns》举例说明单例模式的使用方法和注意事项。
为什么我们不用全局变量,而使用单例呢?
原因大致有四点,第一,全局变量不是OO设计所提倡的;第二,使用全局变量的形式并不能阻止用户创建多个类的实例;第三,对全局变量不能高效地使用lazy initialization。
当然如果静态类是self-constraint,当然可以使用,但是好多时候,对象是需要依赖外部状态的,并且静态类是不能够被继承的。
《Head First》中不提倡subclass单例,因为Singletons are meant to be used sparingly.
《Design Patterns》中,subclass单例后,可以不改变使用着的代码作为单例模式的一个优势来介绍,而且单例模式可以不“单例”,可以创建多个实例。
以下C++代码,则实现了如此功能,当然生成多个实例的单例模式有很多弊端,在本例中,子类的必须实例化才能够在registry中注册,因此违背了lazy initialization的原则。
public class ChocolateBoiler { private boolean empty; private boolean boiled; private volatile static ChocolateBoiler uniqueInstance; private ChocolateBoiler() { empty = true; boiled = false; } public static ChocolateBoiler getInstance() { if (uniqueInstance == null) { synchronized (ChocolateBoiler.class) { if (uniqueInstance == null) { uniqueInstance = new ChocolateBoiler(); } } } return uniqueInstance; } public void fill() { if (isEmpty()) { empty = false; boiled = false; } } public void drain() { if (!isEmpty() && isBoiled()) { empty = true; } } public void boil() { if (!isEmpty() && !isBoiled()) { boiled = true; } } public boolean isEmpty() { return empty; } public boolean isBoiled() { return boiled; }}关于此处几个关键字,具体可以参见《Header First Design Patterns》介绍singleton章节。