zoukankan      html  css  js  c++  java
  • Singleton模式在C#与C++中的实现

    Singleton应该可以算是GOF23个模式中最简单的一个模式了,它有两个要求:一是保证一个类仅有一个实例;二是提供一个访问它的全局访问点。这在实现中分别对应为:一是构造函数非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 class
    ExampleSingleton.Instance.Write();


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

    class ExampleSingleton
    {
        
    // code to support Singleton
    protected:
            ExampleSingleton(){}
    public:
        
    static ExampleSingleton& Instance()
        {
            
    static ExampleSingleton instance;
            
    return instance;
        }

        
    // This class's real functionalities
        void Write(){printf("Hello, World!");}
    };

    // use this singleton class
    ExampleSingleton::Instance().Write();


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

    // Singleton base class, each class need to be a singleton should 
    // derived from this class
    public 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 class
    ExampleSingleton.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 class
    template <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 class
    ExampleSingleton::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模板基类这种机制,以上问题就不会存在,我们得到的不仅仅是节约几行代码:)

    (搬自以前blog, 2007-07-17)

  • 相关阅读:
    java 实现图表展示
    jar包可以到maven下载
    eclipse java ee 添加jrebel 工具
    单链表逆序
    面试-准备
    面试基础知识整理
    mysql中CONCAT值为空的问题解决办法
    数字签名 数字证书
    java 内存泄露分析(jmap + MemoryAnalyzer)
    Chrome 控制台console的用法
  • 原文地址:https://www.cnblogs.com/baiyanhuang/p/1730741.html
Copyright © 2011-2022 走看看