在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?在实现这种机制时应遵寻这样一个原则:
这应该是类设计者的责任,而不是使用者的责任。
Singleton模式的意图:保证一个类仅有一个实例,并提供一个该实例的全局访问点。
示例代码:
在Singleton这个类中,这里要注意的是,我们会提供一个private的类构造器,这时如用这样的一段代码去实例化一个对象就不行了Singleton singleton = new Singleton(),这就防止了用户随意new一个对象实例。而对象的实例化则是通过我们提供的一个Static属性来实现,代码简单易懂,不多说了。
上面代码的另一种实现式:
这两种写法其实是等价的,都可以达到同样的效果,可以用下面的这一段代码来测试,
如果两个对象是同一个的话,那么它们的引用应该是一样的,也就是保证了对象的唯一。
单线程Singleton模式的几个要点:
• Singleton模式中的实例构造器可以设置为protected以允许子类派生。
• Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
• Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
• Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
• 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。
多线程环境下Singleton模式的实现:
用线程的lock机制加上双判断来实现,用双判断是因为可能在第一个判断之后而加锁之前有其它的地方已经实例化了,所以在加锁之后再进行一次判断。
不过这段代码看上有些冗长,如果用下面这代码就好多了
这种方式就相当于实现了一个静态的构造器,它等同于下面的代码
但是这种写法也是有缺点的,因为上面的示例都是在构造器里没有参数的,可以用一个静态的属性来提供对象实例化的访问点,假如现在要求在构造类时传两个参数,那就不能属性的方式来实现了,因为C#里属性器不能传参,这时就需要用一个静态的方法来实现,那么上面的这种多线程的实现方法就不行了,因为静态的构造器在C#里是由系统自己调用的,所以不能给静态构造器传参。如果使用这种方式,就要想其它的参数传递方法了。