在软件工程中,设计模式(Design Pattern)是对软件设计普遍存在(反复出现)的各种问题,锁提出的解决防范。根据模式的目的来划分的话,GoF(Gang of Four) 设计模式可以分为以下三种类型:
1.创建型模式:用来描述“如何创建对象”,它的主要特点是“将对象的创建和使用分离”。包括单例、原型、工厂方法、抽象工厂和建造者5种模式。
2.结构型模式:用来描述如何将类或对象按照某种布局组成更大的结构。包括代理、适配器、侨接、装饰、外观、享元和组合7种模式。
3.行为型模式:用来识别对象之间的常用交流模式以及如何分配职责。包括模版方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录和解释器11种模式。
今天介绍1种常用的设计模式。
一、单例模式
单例模式(Singleton Pattern)是一种常用的模式,有一些对象我们往往只需要一个,比如全局缓存、浏览器中的window对象等。单例模式用于保证一个类仅有一个实例,并提供一个访问它的全局访问点。注意以下几点:
单例类只能由一个实例化对象。
单例类必须自己提供一个实例化对象。
单例类必须提供一个可以访问唯一实例化对象。
单例类必须提供一个可以访问唯一实例化对象的接口。
单例模式分为懒汉和饿汉两种实现方式。
懒汉单例模式
懒汉:顾名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化一个对象。在访问量较小,甚至可能不会去访问的情况下,采用懒汉实现,这是以时间换空间。
非线程安全的懒汉单例模式
//懒汉式一般实现:非线程安全,getInstance返回的实例指针需要delete
class Singleton {
public:
static Singletion* getInstance();
~Singleton(){}
private:
Singleton(){} //构造函数私有
Singleton(const Singleton& obj) = delete; // 明确拒绝
Singleton& operator=(const Singleton& obj) = delete; //明确拒绝
static Singleton* m_pSingletion; // 静态(static)成员;不是任意对象的组成部分,但由给定类的全体对象所共享的数据成员或函数成员。
};
Singleton* Singleton::m_pSingleton = NULL;
Singleton* Singleton::getInstance() {
if (m_pSingleton == NULL) {
m_pSingleton = new Singleton;
}
return m_pSingleton;
}
线程安全的懒汉单例模式
std::mutex mt;
class Singleton {
public:
static Singleton* getInstance();
private:
Singleton(){} // 构造函数私有
Singleton(const Singleton&) = delete; // 明确拒绝
Singleton& operator=(const Singleton&) = delete; // 明确拒绝
static Singleton* m_pSingleton;
};
Singleton* Singleton::m_pSingleton = NULL;
Singleton* Singleton::getInstance() {
if(m_pSingleton == NULL) {
mt.lock();
if(m_pSingletion == NULL) {
m_pSingleton = new Singleton();
}
mt.unlock();
}
return m_pSingleton;
}
返回一个reference指向local static对象
这种单例模式实现方式多线程可能存在不确定性:任何一种non-const static对象,不论它是local或non-local,在多线程环境下“等待某事发生”都会有麻烦。解决的方法:在程序的单线程启动阶段手工调用所有reference-returning函数。这种实现方式的好处是不需要去delete它。
class Singleton{
public:
static Singleton& getInstance();
private:
Singleton(){}
Singleton(const Singleton&) = delete; //明确拒绝
Singleton& operator=(const Singleton&) = delete; //明确拒绝
};
Singleton& Singleton::getInstance() {
static Singleton singleton;
return singleton;
}
饿汉单例模式
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。在访问量比较大,或者访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
// 饿汉式:线程安全,注意一定要在合适的地方去delete它
class Singleton {
public:
static Singleton* getInstance();
private:
Singleton(){} //构造函数私有
Singleton(const Singleton&) = delete; //明确拒绝
Singleton& operator=(const Singleton&) = delete; //明确拒绝
static Singleton* m_pSingleton;
};
Singleton* Singleton::m_pSingleton = new Singleton();
Singleton* Singleton::getInstance() {
return m_pSingleton;
}
应用场景:
需要频繁实例化然后销毁的对象。
创建对象时消耗过多或消耗资源过多,但又经常用到的对象。
系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。



