zoukankan      html  css  js  c++  java
  • (原创)c++11改进我们的模式之改进单例模式

    我会写关于c++11的一个系列的文章,会讲到如何使用c++11改进我们的程序,本次讲如何改进我们的模式,会讲到如何改进单例模式、观察者模式、访问者模式、工厂模式、命令模式等模式。通过c++11的改进,我们的模式变得更通用、更简洁、更强大。本次讲如何改进单例模式。

    在c++11之前,我们写单例模式的时候会遇到一个问题,就是多种类型的单例可能需要创建多个类型的单例,主要是因为创建单例对象的构造函数无法统一,各个类型的形参不尽相同,导致我们不容易做一个所有类型都通用的单例。现在c+11帮助我们解决了这个问题,解决这个问题靠的是c++11的可变模板参数。直接看代码。

    template <typename T>
    class Singleton
    {
    public:
    template<typename... Args>
      static T* Instance(Args&&... args)
      {

            if(m_pInstance==nullptr)

                m_pInstance = new T(std::forward<Args>(args)...);

            return m_pInstance;

        }

      static T* GetInstance()
      {
        if (m_pInstance == nullptr)
          throw std::logic_error("the instance is not init, please initialize the instance first");

        return m_pInstance;
      }

    static void DestroyInstance()
        {
            delete m_pInstance;
            m_pInstance = nullptr;
        }
    
    private:
            Singleton(void);
            virtual ~Singleton(void);
            Singleton(const Singleton&);
            Singleton& operator = (const Singleton&);
    private:
        static T* m_pInstance;
    };
    
    template <class T> T*  Singleton<T>::m_pInstance = nullptr;

    这个单例模式可以解决不同类型构造函数形参不尽相同的问题,真正意义上对所有类型都通用的单例模式。

    /***********更新说明****************/

    由于原来的接口中,单例对象的初始化和取值都是一个接口,可能会遭到误用,更新之后,讲初始化和取值分为两个接口,单例的用法为:先初始化,后面取值,如果中途销毁单例的话,需要重新取值。如果没有初始化就取值则会抛出一个异常。

    增加Multiton的实现

    #include <map>
    #include <string>
    #include <memory>
    using namespace std;
    
    template < typename T, typename K = string>
    class Multiton
    {
    public:
        template<typename... Args>
        static std::shared_ptr<T> Instance(const K& key, Args&&... args)
        {
            return GetInstance(key, std::forward<Args>(args)...);
        }
    
        template<typename... Args>
        static std::shared_ptr<T> Instance(K&& key, Args&&... args)
        {
            return GetInstance(key, std::forward<Args>(args)...);
        }
    private:
        template<typename Key, typename... Args>
        static std::shared_ptr<T> GetInstance(Key&& key, Args&&...args)
        {
            std::shared_ptr<T> instance = nullptr;
            auto it = m_map.find(key);
            if (it == m_map.end())
            {
                instance = std::make_shared<T>(std::forward<Args>(args)...);
                m_map.emplace(key, instance);
            }
            else
            {
                instance = it->second;
            }
    
            return instance;
        }
    
    private:
        Multiton(void);
        virtual ~Multiton(void);
        Multiton(const Multiton&);
        Multiton& operator = (const Multiton&);
    private:
        static map<K, std::shared_ptr<T>> m_map;
    };
    
    template <typename T, typename K>
    map<K, std::shared_ptr<T>> Multiton<T, K>::m_map;

    c++11 boost技术交流群:296561497,欢迎大家来交流技术。

  • 相关阅读:
    BZOJ4944 泳池 解题报告
    简短的开始
    树链剖分的一种妙用与一类树链修改单点查询问题的时间复杂度优化——2018ACM陕西邀请赛J题
    三月月考暨省队选拔
    Luogu P1245 电话号码
    JXOJ(基于UOJ)部署日志
    入学考试总结_20190310
    十二月月考之生物总结
    寒假作业完成进度
    discuz在windows下的环境配置遇到的问题总结
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3145019.html
Copyright © 2011-2022 走看看