C++设计模式:单例模式 | Word count: 1.1k | Reading time: 4min
记录学习C++的设计模式的足迹。
Singleton(单例)模式 Singleto要解决的问题是如何:整个程序只创建一个唯一的变量(对象)? 在面向过程中
(c),只需要创造唯一的全局变量,好的设计会用结构体等将其封装,以减少全局变量的暴露和冲突。 在面向对象
的中(c++),以类的形式实现的全局变量就被称为Singleton(单例)模式(全局唯一,修改可全局更新)。
线程安全 单例对象在整个程序中只实例一次,之后访问该对象都通过它自身的接口。在多线程中,单例对象可能被同时访问,数据被同时修改,造成对数据的不一致性。因此对单例数据需要实现用同步机制来保证各个线程安全访问。
共享资源同步机制
1.给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。 2.让线程也拥有资源,不用去共享进程中的资源。
单例实现 单例实现懒汉模式
和饥饿模式
,它们区别在于实例的时间点不同,懒汉模式
在需要时在创建,饿汉模式
在程序开始执行时就创建。
懒汉模式 :以时间换空间,适应于访问量较小的共享数据。
饿汉模式 :以空间换时间,适应于访问量较大的共享数据,或者线程比较多。
单例的特点
1.构造函数和析构函数属性是private,可以禁止外部构造和析构。
2.拷贝构造和赋值构造函数属性是private,可以禁止外部拷贝和赋值,保证实例的唯一性。
3.类的成员中有获取实例的静态函数,外部可以通过该API全局访问。
懒汉模式 系统运行中,单例的实例并不存在,当需要使用该单例实例时,会去创建并使用实例。多线程时可能同时创建,需要通过加锁
的方式保证安全。
懒汉模式(加锁) lock_lazy_singleton.h link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #ifndef LOCK_LAZY_SINGLETON_H #define LOCK_LAZY_SINGLETON_H #include <iostream> #include <mutex> using namespace std; class LockLazySingleton{ public: static LockLazySingleton* GetInstace(); string name_; int age_; private: LockLazySingleton(); virtual ~LockLazySingleton(); LockLazySingleton(const LockLazySingleton&); LockLazySingleton& operator=(const LockLazySingleton&); static LockLazySingleton *m_instanceSingleton; static std::mutex mtx; }; #endif
lock_lazy_singleton.cpp link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include "lock_lazy_singleton.h" LockLazySingleton* LockLazySingleton::m_instanceSingleton = nullptr; std::mutex LockLazySingleton::mtx; LockLazySingleton::LockLazySingleton() { std::cout << "Create LockLazySingleton" << std::endl; } LockLazySingleton::~LockLazySingleton() { } LockLazySingleton* LockLazySingleton::GetInstace() { if (m_instanceSingleton == NULL ) { mtx.lock(); if (m_instanceSingleton == NULL ) { m_instanceSingleton = new LockLazySingleton; } mtx.unlock(); } return m_instanceSingleton; }
懒汉模式(局部成员) unlock_lazy_singleton.h link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #ifndef UNLOCK_LAZY_SINGLETON_H #define UNLOCK_LAZY_SINGLETON_H #include <iostream> #include <mutex> using namespace std; class UnlockLazySingleton{ public: static UnlockLazySingleton& GetInstace(); string name_; int age_; private: UnlockLazySingleton(); virtual ~UnlockLazySingleton(); UnlockLazySingleton(const UnlockLazySingleton&); UnlockLazySingleton& operator=(const UnlockLazySingleton&); }; #endif
unlock_lazy_singleton.cpp link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include "unlock_lazy_singleton.h" UnlockLazySingleton::UnlockLazySingleton() { std::cout << "Create UnlockLazySingleton." << std::endl; } UnlockLazySingleton::~UnlockLazySingleton() { } UnlockLazySingleton& UnlockLazySingleton:: GetInstace() { static UnlockLazySingleton unlock_lazy_singleton; return unlock_lazy_singleton; }
饿汉模式 程序一执行,就初始化创建单例实例,之后直接调用。
hunger_singleton.h link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #ifndef HUNGER_SINGLETON_H #define HUNGER_SINGLETON_H #include <iostream> using namespace std; class HungerSingleton{ public: static HungerSingleton* GetInstace(); string name_; int age_; private: HungerSingleton(); virtual ~HungerSingleton(); HungerSingleton(const HungerSingleton&); HungerSingleton& operator=(const HungerSingleton&); static HungerSingleton *m_instanceSingleton; }; #endif
hunger_singleton.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "hunger_singleton.h" HungerSingleton* HungerSingleton::m_instanceSingleton = new HungerSingleton; HungerSingleton::HungerSingleton() { } HungerSingleton::~HungerSingleton() { } HungerSingleton* HungerSingleton::GetInstace() { return m_instanceSingleton; }
调用方法 main.cpp link 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include <iostream> #include "lock_lazy_singleton.h" #include "unlock_lazy_singleton.h" #include "hunger_singleton.h" using namespace std; void ShowLockLazySingleton(){ LockLazySingleton *lock_lazy_singleton = LockLazySingleton::GetInstace(); cout << lock_lazy_singleton->name_ << endl; cout << lock_lazy_singleton->age_ << endl; } void ShowUnLockLazySingleton(){ cout << UnlockLazySingleton::GetInstace().name_ << endl; cout << UnlockLazySingleton::GetInstace().age_ << endl; } void ShowHungerSingleton(){ HungerSingleton* hunger_singleton = HungerSingleton::GetInstace(); cout << hunger_singleton->name_ << endl; cout << hunger_singleton->age_ << endl; } int main(){ LockLazySingleton *lock_lazy_singleton = LockLazySingleton::GetInstace(); lock_lazy_singleton->name_ = "xiao ming" ; lock_lazy_singleton->age_ = 24 ; UnlockLazySingleton::GetInstace().name_ = "xiao hong" ; UnlockLazySingleton::GetInstace().age_ = 22 ; HungerSingleton* hunger_singleton = HungerSingleton::GetInstace(); hunger_singleton->name_ = "xiao gang" ; hunger_singleton->age_ = 23 ; ShowLockLazySingleton(); ShowUnLockLazySingleton(); ShowHungerSingleton(); hunger_singleton->name_ = "xiao hua" ; hunger_singleton->age_ = 25 ; ShowHungerSingleton(); return 0 ; }