c++ 设计模式——单例模式

  • 单例模式

    一种常用的软件设计模式。在它的核心结构中只包含一个被称之为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例对象。

    单例模式分为两种:饿汉模式和懒汉模式

  • 应用场景

    1. 需要频繁的实例化然后销毁对象
    2. 创建对象耗时过多或资源消耗过多,但又经常需要用到的对象
    3. 有状态的工具类对象
    4. 频繁访问数据库或文件对象
    5. 设备管理器常常设计为单例模式,比如一个电脑连接有两个打印设备,在输出时就不能两台打印机同时打印一个文件
  • 优点

    1. 在内存中只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
    2. 避免了对资源的多重占用
  • 缺点

    1. 没有借口,不能够继承,与单一职责冲突,一个类应该只关心内部的逻辑,而不关心外面怎么样来实例化
  • 实现

    1. 创建一个类的静态指针变量指向类的唯一实例
    2. 全局唯一公共访问节点来创造对象,函数为public属性
    3. 为使用方便增加一个辅助类来释放资源
  • 饿汉模式

    饿汉模式就是很饿,无论是对象是否需要用到,程序已启动就会创建一个唯一的实例对象。

    • 优点:简单,线程安全
    • 缺点:启动变回加载一个实例,有可能浪费资源。多个单例对象实例启动顺序不可控。
    # ifndef __EAGER_SINGLETON_H_
    # define __EAGER_SINGLETON_H_
    
    # include 
    
    using namespace std;
    //饿汉模式,可以保证线程安全
    class Eager_singleton;
    class Eager_singleton{
    public:
    	static Eager_singleton* GetInstance(){
    		return m_instance;
    	}
    
    	//私有的内嵌类
    	class CGarb{
    	public:
    		~ CGarb(){
    			if(nullptr != Eager_singleton::m_instance){
    				delete Eager_singleton::m_instance;
    				m_instance = nullptr;
    			}
    		}
    	};
    
    private:
    	Eager_singleton (){;}
    	Eager_singleton& operator=(const Eager_singleton);
    
    	static Eager_singleton* m_instance;
    	static CGarb garb1;
    };
    Eager_singleton* Eager_singleton::m_instance = new Eager_singleton();
    Eager_singleton::CGarb garb1;
    
    # endif
    
  • 懒汉模式

    懒汉模式就是已经懒到极致了,单例实例当首次被引用时才进行初始化,尽量使资源的利用最大化。如常见的晚绑定、写时拷贝技术都是这种实现方式。

    • 优点:进程启动无负载,多个单例启动顺序可控制
    • 缺点:复杂,线程不安全
    # ifndef __LAZY_SINGLETON_H_
    # define __LAZY_SINGLETON_H_
    
    # include 
    
    using namespace std;
    
    //加工过的懒汉模式,也可以保证线程安全
    class Lazy_singleton;
    class Lazy_singleton{
    public:
    	static Lazy_singleton* GetInstance(){
    		//double-check双重验证的方式以及加锁可以保证效率和线程安全
    		if(nullptr == m_instance){
    			m_mtx.lock();
    			if(nullptr == m_instance){
    				m_instance = new Lazy_singleton();
    			}
    			m_mtx.unlock();
    		}
    		return m_instance;
    	}
    
    	//私有的内嵌类
    	class CGarb{
    	public:
    		~ CGarb(){
    			if(nullptr != Lazy_singleton::m_instance){
    				delete Lazy_singleton::m_instance;
    				m_instance = nullptr;
    			}
    		}
    	};
    
    private:
    	Lazy_singleton(){;}
    
    	Lazy_singleton(Lazy_singleton const &);
    	Lazy_singleton& operator=(Lazy_singleton const &);
    
    	static Lazy_singleton* m_instance;
    	static mutex m_mtx;
    	static CGarb garb;
    };
    
    Lazy_singleton* Lazy_singleton::m_instance = nullptr;
    mutex Lazy_singleton::m_mtx;
    Lazy_singleton::CGarb garb;
    
    
    # endif
    
  • 测试实例:

    # include 
    # include 
    # include "lazy_singleton.h"
    # include "eager_singleton.h"
    
    using namespace std;
    
    int main(){
        Lazy_singleton * lazy1 = Lazy_singleton::GetInstance();    
        Lazy_singleton * lazy2 = Lazy_singleton::GetInstance();    
        cout << "lazy1 : " << lazy1 << endl;
        cout << "lazy2 : " << lazy2 << endl;
    
        Eager_singleton * lazy3 = Eager_singleton::GetInstance();    
        Eager_singleton * lazy4 = Eager_singleton::GetInstance();    
        cout << "lazy3 : " << lazy3 << endl;
        cout << "lazy4 : " << lazy4 << endl;
        return 0;
    }
    

    输出结果:

    [cc@localhost designMode]$ g++ singleton_test.cc -std=c++0x
    [cc@localhost designMode]$ ./a.out 
    lazy1 : 0x1f6e030
    lazy2 : 0x1f6e030
    lazy3 : 0x1f6e010
    lazy4 : 0x1f6e010
    

你可能感兴趣的:(c++,设计模式,设计模式)