Singlton设计模式

时间:2023-03-10 02:32:46
Singlton设计模式
  • 单例定义:

    确保一个类只有一个实例,并提供全局访问点。

  • 适用场景:

    1.) 当系统中某个类必须仅有一个实例对象,同时访问该系统的所有访问者必须访问同一个实例对象时,且该对象实例自身占用资源又不大时。

    2.) 在C/s应用程序中,当我们要保证某一个非模式窗口,只能显示一个实例时。

  • 举例适用场景:

    线程池(threadpool)、缓存(cache)、对话框、处理编好设置和注册表(registry)的对象、日志对象,充当打印机、显卡等设备的驱动程序对象。这些类对象只能有一个实例,如果造出多个实例,就会导致许多问题产生,例如:程序的行为异常、资源适用过量,或者是不一致的结果。

  • 实现推荐方案:   
 /// <summary>
/// Description of SiteSettings.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance=null;
private static object locker=new object(); private SiteSettings()
{
} public static SiteSettings Instance {
get {
if(instance==null)
{
Console.WriteLine("Install equals null.");
lock(locker)
{
if(instance ==null)
{
Console.WriteLine("new SiteSettings instance.");
instance=new SiteSettings();
}
}
}
return instance;
}
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}

  调用:

 class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!"); // TODO: Implement Functionality Here Console.WriteLine(SiteSettings.Instance.SiteClosed);
Console.WriteLine(SiteSettings.Instance.SiteClosed);
SiteSettings.Instance.SiteClosed=true;
Console.WriteLine(SiteSettings.Instance.SiteClosed); Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}

  运行结果:

Singlton设计模式

  • 其他实现方案:

  1.) 方案1     

/// <summary>
/// Description of MemberBO.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance=null;
private static object locker=new object(); private SiteSettings()
{
} public static SiteSettings Instance {
get {
if(instance ==null){
Console.WriteLine("Install equals null.");
lock(locker){
Console.WriteLine("Enter locker.");
Console.WriteLine("new SiteSettings instance.");
instance=new SiteSettings();
}
}
return instance;
}
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}

  2.) 方案2:     

/// <summary>
/// Description of MemberBO.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance=null;
private static object locker=new object(); private SiteSettings()
{
} public static SiteSettings Instance {
get {
Console.WriteLine("Install equals null.");
lock(locker){
if(instance ==null){
Console.WriteLine("Enter locker.");
Console.WriteLine("new SiteSettings instance.");
instance=new SiteSettings();
}
}
return instance;
}
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}

  3.) 方案3: 

/// <summary>
/// Description of MemberBO.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance=null;
private static object locker=new object(); private SiteSettings()
{
} public static SiteSettings Instance {
get {
Console.WriteLine("Install equals null.");
if(instance ==null){
Console.WriteLine("new SiteSettings instance.");
instance=new SiteSettings();
}
}
return instance;
}
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}

  4.) 方案4:

/// <summary>
/// Description of SiteSettings.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance= new SiteSettings(); private SiteSettings()
{
} public static SiteSettings Instance {
get {
return instance;
}
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}

  5.) 方案5:

/// <summary>
/// Description of SiteSettings.
/// </summary>
public class SiteSettings
{
private static SiteSettings instance=null;
private static object locker=new object(); private SiteSettings()
{
} public static SiteSettings GetInstance() {
if(instance==null){
locker(locker){
if(instance==null){
instance=new SiteSettings();
}
}
}
return instance;
} private bool siteClosed=false; public bool SiteClosed {
get { return siteClosed; }
set { siteClosed = value; }
}
}
  • 为什么不推荐方案1,方案2,方案3:
  1. 方案1,虽然考虑了线程安全,但还不是足够的安全,还没有双重锁定安全
  2. 方案2,虽然考虑了线程安全,但每次都要进入locker,即使instance对象已经赋值后
  3. 方案3,线程安全问题就没有考虑。
  • 适当的情况下可以选择方案4,方案5
  1. 方案4,使用“迫切”创建实例(当应用程序启动,初始化系统时,初始化全局变量时创建对象实例),而不用延迟实例化的方法
  2. 方案5,采用了延迟实例化的方法。
  • 注意混淆问题:

  不要和Monitor,ReaderWriterLockSlim等这些线程安全的使用方式混淆。

1.) Monitor:提供同步访问对象的机制。

2.) ReaderWriterLockSlim:表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。

  • 优缺点:

  1.)优点:

    a.)确保了系统中保存一个实例对象,为程序带来了开拓思路;

    b.)内存开销可能会占用一定空间,但它避免了每次都需要开辟空间的消费;

    c.)使得程序能逻辑清理,开发者可以单一的使用该实例对象去操作,而不别每次都要new一个实例对象来进行操作。

  2.缺点:

    a.)多个用户在操作这个对象时,线程的安全性,就需要考虑。

    b.)一直在占用资源,而不可以被回收。

参考资料:《Head First 设计模式》

  欢迎拍砖!请牛人们给指点。