设计模式一:单例模式的原理,c++实现,以及应用实例
单例模式的由来(需求产生特性)
对于一般的方法类,例如计算数据中的众数,一般可以写一个专门的函数 f() 来方便我们调用。但是在面向对象编程的过程中,也应该将方法设计成类的方式。这里如果将 f() 放到类中,每一次调用都实例化出一个对象,也是可以完成需求的。但是这里调用的 f() 的功能完全一样,没有必要重新实例化对象,产生代码的冗余。
所以我们想创造出一个模式,让类的对象只有一个,并且全局可用,线程安全。
单例模式的两种实现方式
一 饿汉模式
为啥叫做饿汉模式?
因为此模式里面在类创建的时候就已经创建好了唯一的对象,不管有没有需求,它只负责进行创建以备使用。因为这种方式在需求提出前就做好了准备,可以类比人非常着急,称之为饿汉。
饿汉模式c++ 模板
//饿汉模式
//线程安全
class Singleton {
public:
static Singleton& getInstance() { //公有的方法
return instance;
}
private:
static Singleton instance ; //私有的实例 static:由类共享的成员变量
Singleton() { //私有的构造函数
std::cout << "singleton construct" << std::endl;
};
~Singleton() { //私有的析构函数
std::cout << "singleton deconstruct" << std::endl;
}
Singleton& operator=(Singleton& other) = delete; //禁止赋值运算符
Singleton(Singleton& other) = delete;//禁止复制构造函数
};
Singleton Singleton:: instance; //必须定义static
int main() {
Singleton& one_copy = Singleton::getInstance(); //类的共有方法调用方式
getchar();
return 0;
}
如何保证,饿汉模式中实例一定会在调用前创建好?
在单线程中,static对象会在第一次程序执行到该对象的定义处遇到时初始化。所以是没问题的。
在多线程中,有线程安全问题,因为在线程里面,可能出现多个线程同时程序运行到一个类。但是我们定义的是一个静态对象,在程序运行之出就会进行分配空间、进行初始化。所以也没问题。
二 懒汉模式
为什么叫他懒汉模式?
因为“懒”,只有在需求出现的时候,才会创建对象或者返回对象。
class Singleton {
public:
static Singleton* getInstance() { //公有的方法 static必须使用static变量
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
private:
static Singleton * instance ; //私有的实例 static:由类共享的成员变量
Singleton() { //私有的构造函数
std::cout << "singleton construct" << std::endl;
};
~Singleton() { //私有的析构函数
std::cout << "singleton deconstruct" << std::endl;
}
//Singleton& operator=(Singleton& other) = delete; //禁止赋值运算符
Singleton(Singleton& other) = delete;//禁止复制构造函数
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* one_copy = Singleton::getInstance(); //类的共有方法调用方式
Singleton* two_copy = Singleton::getInstance(); //类的共有方法调用方式
getchar();
return 0;
}
调用2次,但是只调用了一次构造函数
如何保证懒汉模式线程安全?
懒汉模式需要在程序运行过程中创建唯一的对象,所以保证线程互斥必须保证。
解决方式
双重锁检测
class Singleton {
public:
static Singleton* getInstance() { //公有的方法
if (instance == nullptr) {
g_lock.lock(); //上锁
if (instance == nullptr)
{
instance = new Singleton();
}
g_lock.unlock();//解锁函数
}
return instance;
}
private:
static Singleton * instance ; //私有的实例 static:由类共享的成员变量
Singleton() { //私有的构造函数
std::cout << "singleton construct" << std::endl;
};
~Singleton() { //私有的析构函数
std::cout << "singleton deconstruct" << std::endl;
}
Singleton& operator=(Singleton& other) = delete; //禁止赋值运算符
Singleton(Singleton& other) = delete;//禁止复制构造函数
};
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex g_lock;
class Singleton {
public:
static Singleton* getInstance() { //公有的方法
if (instance == nullptr) {
g_lock.lock(); //上锁
if (instance == nullptr)
{
instance = new Singleton();
}
g_lock.unlock();//解锁函数
}
return instance;
}
private:
static Singleton * instance ; //私有的实例 static:由类共享的成员变量
Singleton() { //私有的构造函数
std::cout << "singleton construct" << std::endl;
};
~Singleton() { //私有的析构函数
std::cout << "singleton deconstruct" << std::endl;
}
Singleton& operator=(Singleton& other) = delete; //禁止赋值运算符
Singleton(Singleton& other) = delete;//禁止复制构造函数
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* one_copy = Singleton::getInstance(); //类的共有方法调用方式
Singleton* two_copy = Singleton::getInstance(); //类的共有方法调用方式
getchar();
return 0;
}