Singleton 单一实例

本文深入探讨了Singleton模式的实现方式,介绍了如何通过基类模板减少重复代码,保持行为一致性,便于后期维护。并对比了C#与C++两种语言中的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Singleton应该可以算是GOF的23个模式中最简单的一个模式了,它有两个要求:一是保证一个类仅有一个实例;二是提供一个访问它的全局访问点。这在实现中分别对应为:一是构造函数非public;二是提供一个静态函数作为全局访问点。 

在C#中,我们可以这么写:

public class ExampleSingleton{   

 // code to support Singleton   

 protected ExampleSingleton()

}   

 protected static ExampleSingleton instance = new ExampleSingleton();  

  public static ExampleSingleton Instance  

  {        get{return instance;} 

   }    // This class's real functionalities   

 public void Write(){Console.WriteLine("Hello, World!");}

}

// use this singleton classExampleSingleton.Instance.Write(); 

   类似的,C++中实现如下:

 class ExampleSingleton{   

 // code to support Singletonprotected:      

  ExampleSingleton()

{}

public:    static ExampleSingleton& Instance()    

{    

    static ExampleSingleton instance;   

     return instance;    }    

// This class's real functionalities  

  void Write()

{printf("Hello, World!");}

};

// use this singleton 

classExampleSingleton::Instance().Write();   

 这样写的确符合了singleton的两个要求,但是如果我们的系统中有许多个Singleton类,而对于每一个类,我们都要写那些固定的,重复的代码去支持其singleton的属性。这不是一个好现象,我们希望可以把这些固定的代码提取出来,使我们的Singleton类只需要专注于实现其真正的功能,相信很多人都听说过这个做法:Singleton模板基类。对于C#:

// Singleton base class, each class need to be a singleton should 

// derived from this classpublic 

class Singleton<T> where T: new()

{       

 // Instead of compile time check, we provide a run time check   

 // to make sure there is only one instance.   

 protected Singleton()

{

Debug.Assert(null == instance);}  

  protected static T instance = new T(); 

   public static T Instance   

 {        get{return instance;} 

   }

}

// Concrete singleton class, derived from Singleton<T>public class ExampleSingleton: Singleton<ExampleSingleton>{   

 // since there is no "freind class" in C#, we have to make  

  // this contructor public to support the new constraint.    public ExampleSingleton(){}    

// This class's real functionalities   

 public void Write(){Console.WriteLine("Hello, World!");

}

}

// use this singleton classExampleSingleton.Instance.Write();

这里,我们把为了支持Singleton功能的代码提到一个Singleton<T>的类模板当中,任何需要成为Singlton的类,只需从其派生便自然获得Singleton功能。这里的一个问题是:为了支持模板类中的new()constraint,我们不得不把作为具体singleton类的派生类的构造函数作为public,这就导致我们无法在编译期阻止用户自行new出第二个,第三个实例来,但我们可以在运行期来进行检查进而保证其实例的单一性,这就是这singleton基类构造函数的作用: protected Singleton(){Debug.Assert(null == instance);}     当然,有另外一种实现方法,那就是singleton基类不提供new() constraint, 这样我们就可以让ExampleSingleton的构造函数为非public,在要创建T实例的时候,由于不能使用new, 我们用reflection反射出类型T的非public构造函数并调用之。这样,我们的确能保证编译期实例的唯一性,但是由于用了反射,感觉代码不是那么的简单优雅,并且对其性能持保留态度,所以不太倾向与这种方法。     但毕竟是越早检查出错误越好,所以大家如果有好的解决方案,不妨提出来一起讨论讨论。而C++中由于提供了友元这个特性,实现起来要好一些:

// Singleton base class, each class need to be a singleton should 

// derived from this 

classtemplate <class T> class  Singleton{protected:    Singleton(){}public:    static T& Instance()  

  {        static T instance;        return instance;  

  }

};

// Concrete singleton class, derived from Singleton<T>class ExampleSingleton: public Singleton<ExampleSingleton>{    

// so that Singleton<ExampleSingleton> can access the     

// protected constructor    friend class Singleton<ExampleSingleton>;

protected:        ExampleSingleton(){}public:    

// This class's real functionalities   

 void Write(){printf("Hello, World!");

}

};

// use this singleton

 classExampleSingleton::Instance().Write();

 在C++友元的帮助下,我们成功实现了在编译期保证实例的唯一性。(当然,前提是你不要"乱交朋友")。    有人可能会问,实现singleton的代码并不多,我们没必要搞这么一个机制来做代码复用吧? 的确,我们复用的代码并不是很多,但是,我想代码复用的目的不仅仅是减少代码量,其最重要的目的还是在于保持行为的一致性,以便于使用与维护。(用函数替换代码段便是一个很好的例子)。 对于这里的singleton类来讲,如果不做这个设计,我们在每个具体的singleton类内部实现其singleton机制,那么可能出现的问题是1. 很难保证其接口的一致性张三写了一个singleton类,全局访问函数是Instance, 李四也写了一个Singleton类,全局访问函数可能就是GetInstance了。。。。。我们并没有一个健壮的机制来保证接口的一致性,从而导致了使用的混乱性。 2. 不易维护Singleton创建实例有两种:一种为lazy initialization, 一种就是early initialization, 假如开始的实现是所有的singleton都用lazy initialization, 突然某种需求要求你用early initialization,你的噩梦就开始了,你不得不重写每一个singleton类。而用了singleton模板基类这种机制,以上问题就不会存在,我们得到的不仅仅是节约几行代码:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值