导航

意图:      保证一个类仅有一个实例,并提供一个访问它的全局访问点
适用性:  当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
                  当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能适用一个扩展的实例时
结构图:

实现一:
using System;

namespace DesignPattern
{
 /// <summary>
 /// Singleton1 的摘要说明。
 /// 动机: 软件系统中经常遇到这样一些特殊类,必须保证它们在系统中只存在
 ///    一个实例,才能保证它们逻辑的正确性、以及良好的效率。如何绕
 ///    过常规的构造器提供一种机制来保证一个类只有一个实例?
 /// 意图: 保证一个类仅有一个实例,并提供一个该实例的全局访问点。
 /// 要点: 1、实例构造器可以设置为protected以允许子类派生
 ///   2、一般不要支持ICloneable接口,因为可能导致多个对象实例
 ///   3、一般不要支持序列化,因为也可能导致多个对象实例
 ///   4、只考虑对象创建的管理,未考虑对象销毁的管理。对支持垃圾
 ///    回收的平台和对象的开销而言,可以不进行销毁管理
 ///   5、不能应对多线程环境:多线程环境下使用它仍然可能得到多个实例
 /// </summary>
 public class Singleton1
 {
  private static Singleton1 instance;
  //晚加载,所以不在此处直接instance = new Singleton1();而在Instance
  //中直接返回        
  private Singleton1(){ }//避免随意new

  public static Singleton1 Instance
  {
   get
   {
    if(instance == null)
    {
     instance = new Singleton1();
    }
    return instance;
   }
  }  
 }
实现二:
using System;

namespace DesignPattern
{
 /// <summary>
 /// Singleton2 的摘要说明。
 /// </summary>
 public class Singleton2
 {
  private static volatile Singleton2 instance;
  //volatile,使编译器不对代码调整,严格保证多线程中不出现多个对象
  private static object lockHelper = new object();
  //lock(this)可不可以?!
  
  private Singleton2(){}
  public static Singleton2 Instance
  {
   get
   {
    if(instance == null)
    {
     lock(lockHelper)
     {
      if(instance == null)
      {
       instance = new Singleton2();
      }
     }
    }
    return instance;
   }
  } 
 }
}
实现三:
using System;

namespace DesignPattern
{
 /// <summary>
 /// Singleton3 的摘要说明。
 /// </summary>
 sealed class Singleton3
 //不需要子类继承则用sealed,需要则class Singleton3
 {
  public static readonly Singleton3 Instance = new Singleton3();
  //静态只读,内联初始化
  private Singleton3(){}
 }

// 等同于
// (sealed) class Singleton
// {
//  public static readonly Singleton Instance;
//  static Singleton()
//  //静态构造器,执行时间BeforeFieldInit,只在静态字段初始化之前执行
//  //DOTNET机制保证只有一个线程执行它,相当于自动加锁
//  //弊端:不支持参数化构造器,可以通过添加属性解决
//  //也可以将另外一些资源初始化之类的操作放到一个辅助性函数中Init() 
//  //中完成,实例化后调用它
//  {
//   Instance = new Singleton();
//  }
//  private Singleton(){}
// }

}