原创文章,如有转载,请注明出处:
http://blog.csdn.net/neomc/article/details/6787876
单件模式时管理互斥/共享/临界资源的不错方式。可以保证系统所用的全局资源只有一份。
单件模式的定义:确保一个类只有一个实例,并且提供一个全局访问点。
单件模式的优点:
1. 可以延迟实例化。类只有在被真正使用时才会被实例化,避免了如全局变量那样的需要在一开始就实例化。
2. 能够保证这个程序运行期间只有一个类的实例。有时一些场合只允许一个类被实例化一次。
3. 全局变量本身并不是一种很好的设计(变量作用域里所有的地方都可以修改他),单件模式可以有一定的控制。
单件模式的缺点:
1. 提供类似于全局变量的功能,可能会被滥用。真正需要这种模式的地方不会很多。
2. 当父类使用单件模式时,子类如果想继承父类,会遇到父类的构造函数是私有类型。不能用父类的私有构造函数来扩展类(子类实例化时无法自动调用父类构造函数)。如果将父类构造函数改成公有或者保护的,破坏了单件模式的作用(别的类可以实例化他了,并且所用子类都使用同一个父类的实例,你并不一定想这样做)。
3. 违反了单一职责原则。当然,单件模式带来的好处应该大于违反这一原则的弊端。毕竟OO原则并不总是会被完全实现。
一个可以想到的单件模式实现如下:
1 | public MyClass { |
2 | private static MyClass myclass; |
3 | private MyClass() {} |
4 | |
5 | public static MyClass getInstance() { |
6 | if(myclass == null) |
7 | myclass = new MyClass(); |
8 | return myclass; |
9 | } |
10 | } |
如上所示,代码可以保证MyClass在程序运行时只会被实例化一次,不会被多次创建。
这里多说一句,如果类的构造函数被设置成了私有属性,一般的new的方法是不能实例化这个类的。单件模式是一个可行的实例化方法。另外,还可是使用友元类实现,不再赘述。
单件模式本身有一个很大的缺点:在多线程模式下,如果没有同步机制将有可能若干线程同时进入临界区代码,从而多次实例化类(大家可以想想这是为什么)。
要解决这个问题,有三种方法:
1. 什么都别做。
是的,这也是一种方法。如果你的程序本身就是单线程,或者可以承受这种缺点带来的负担,就不要去修改单件模式了。要知道同步一个方法可能会使你的程序效率下降很多。
2. “急切”的创建实例。
在类中声明变量时就初始化。这样虽然可能类在整个程序运行期间未被使用导致内存浪费,但是可以因为是在程序加载时就创建对象了,可以保证类只被实例化一次,代码如下:
public MyClass { private static MyClass myclass = new MyClass(); private MyClass() {} public static MyClass getInstance() { return myclass; } }
3. ”双重检查加锁”
如果是java实现,可以将类中的静态变量声明为volatile,并通过同步机制两次检查临界代码,达到同步目的:
public class MyClass { private static volatile MyClass myclass; private MyClass() {} public static MyClass getInstance() { if(myclass == null) { synchronized(MyClass.class) { if(myclass == null) { myclass = new MyClass(); } } } return myclass; } }