【C#面向对象设计模式】02. Singleton单件(创建型模式)
0. 模式分类
- 从目的来看:
- 创建型模式:负责对象创建。
- 结构型模式:处理类与对象间的组合。
- 行为型模式:类与对象交互中的职责分配。
- 从范围来看:
- 类模式处理类与子类的静态关系。
- 对象模式处理对象间的动态关系。
1. 动机
- 在软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保他们的逻辑正确性、以及良好的效率。
- 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
- 这应该是类设计者的责任,而不是使用者(客户程序)的责任。
2. 意图
保证一个类仅有一个实例,并且提供一个该实例的全局访问点。实际上是对实例个数的控制。
3. 结构
4. 单线程Singleton模式实现
public class Singleton
{private static Singleton instance;private Singleton() { }public static Singleton Instance{get{if (instance == null){instance = new Singleton();}return instance;}}
}
5. 单线程Singleton模式的几个要点
- Singleton模式中的实例构造器可以设置为protected以允许子类派生。
- Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
- Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
- Singleton模式只考虑到了对象创建的管理,没有考虑到对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
- 不能应对多线程环境,在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。
6. 多线程Singleton模式实现
public class Mul_Singleton
{private static volatile Mul_Singleton instance = null;//volatile 可以保证编译不会对代码进行微调,非常严格的执行代码private static object lockHelper = new object();//辅助语句,只是为了满足lock的需要private Mul_Singleton() { }public static Mul_Singleton Instance{get{if(instance == null){lock(lockHelper)//double check{if (instance == null){instance = new Mul_Singleton();}}}return instance;}}
}
class Static_Singleton
{public static readonly Static_Singleton instance = new Static_Singleton();//.NET的机制导致了静态构造器不可能有多线程执行private Static_Singleton() { }//也能实现多线程,但只能适用于构造器无参的情况
}
public class Mul_Singleton
{//多线程带参private static volatile Mul_Singleton instance = null;private static object lockHelper = new object();private Mul_Singleton(int x, int y) {this.x = x;this.y = y;}public static Mul_Singleton GetInstance(int x, int y){get{if(instance == null){lock(lockHelper)//double check{if (instance == null){instance = new Mul_Singleton(x, y);}else{instance.x = x;instance.y = y;}}}return instance;}}
}
7. Singleton模式扩展
- 将一个实例扩展到n个*(固定个数)*实例,例如对象池的实现。
- 将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
- 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。
8. .NET框架中的Singleton引用
MyClass c1 = new MyClass();
MyClass c2 = new MyClass();Type t1 = c1.GetType();
Type t2 = c2.GetType();Console.WriteLine(t1==t2);
//类型相同,只会有一个实例