意图
保证一个类只有一个实例,并提供一个访问它的全局访问点
---《设计模式》GOF
适用性
-
当类只能由一个实例而且客户可以从一个众所周知的访问点访问它时
-
当这个唯一实例应该时通过子类化可扩展,并且客户应该无需更改代码时就能使用一个扩展的实例时
结构
参与者
-
Singleton
- 定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作
- 可能负责创建它的唯一实例
协作
-
客户只能通过GetInstance 操作访问Singleton的实例
效果
-
对唯一实例的受控访问
-
缩小命名空间
-
允许对操作和表示的精化
-
允许可变数目的实例
-
比类操作更灵活
实现
- 保证一个唯一实例
- 创建Singleton的子类
代码示例
class SingletonStructure
{
public void Test()
{
Singleton.GetInstance().GetInput("Singleton");
}
}
class Singleton
{
private static Singleton _instance = null;
protected Singleton()
{ }
/// <summary>
/// 单线程中没有问题
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
public void GetInput(string str)
{
Console.WriteLine("input string is :" + str);
}
}
关于GetInstance()方法的规范
如果是单线程,示例代码中实现足以满足条件;
但是如果是多线程,则会有线程不安全的状况发生,可以采用以下方式解决;
private static volatile SingleInstance instance;
private SingleInstance() { }
public static SingleInstance Instance
{
get
{
if (null == instance)
{
lock (obj)
{
if (null == instance)
{
instance = new SingleInstance();
}
}
}
return instance;
}
}
需要给intance属性,添加volatile关键字,以确保其在内存读写指令级别不被reorder(否则会发生,先分配内存,然后复制给instance,最后才构造的情况)。此外为了确保多线程中instance的唯一性,需要加锁,双重判空。
如有问题,欢迎斧正!!!!