HeadFirst设计模式学习笔记3-单件模式

原创文章,如有转载,请注明出处:

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;
	}
}




你可能感兴趣的:(HeadFirst设计模式学习笔记3-单件模式)