一、单例模式的界说
单例模式,英文全称Singleton Pattern,是一种创建型设计模式,它包管一个类在程序中仅有一个实例,并对外提供一个访问的该类实例的全局接口。
单例模式通常用于需要控制对象资源的开发场景,一个类只创建一个对象的设计,既可以避免创建过多副本所造成的资源浪费现象,又可以避免引发数据一致性等问题。
在数据库连接、线程池设计、日记系统设计等开发场景,常常利用单例模式来创建对象,可以有用地低落对内存资源的占用。
在编码时,为了防止外部直接通过new关键字创建对象实例,Singleton类的构造函数必须是私有的。
在多线程开发场景,单例模式可以避免多个线程同时访问同一个资源,从而避免资源竞争的问题,如果还需要进一步包管线程安全性,可以在创建实例时添加同步锁。
单例模式在现实生活中的抽象实例:
电力公司:在一个城市或地区,通常只有一个电力公司负责供电,我们可以通过该公司来获取电力服务。
总统办公室:在一个国家,通常只有一个总统办公室负责国家变乱处置惩罚,办公室负责确保国家变乱的一致性和高效运作。
登录系统:用户只需要登录一次就可以打开多个应用程序的界面。
二、单例模式的结构
单例模式重要包含以下组件:
1.Singleton类:这是一个单例类,它在整个系统中只有一个实例。通常利用私有构造函数来创建、利用公共静态成员方法来访问。
2.私有构造函数:为了避免被外部实例化,Singleton类通常会界说一个私有构造函数,使得其他类无法通过调用构造函数创建Singleton的实例对象。
3.私有静态成员变量:Singleton类通常会声明一个私有静态成员变量,用来生存Singleton的唯一实例,且这个静态变量只能在Singleton类内部访问。
4.公共的对外接口:它通常被命名为getInstance(),通过该接口可以获取Singleton的唯一实例对象。该接口利用懒汉/饿汉的方式来实现,在接口内部会先判断实例是否已经存在,如果存在则直接返回,否则创建一个新的实例并返回。
组件之间的工作步调如下:
1.饿汉模式的程序启动:在程序启动的同时就创建好Singleton实例,并提供全局唯一的外部访问接口,外部程序可以直接调用该接口来获取Singleton实例。
2.懒汉模式的程序启动:程序启动时并不会创建Singleton实例,程序在等到单例对象被第一次利用时才创建Singleton实例。
3.接纳私有的静态变量存储已经创建好的Singleton实例。
4.外部客户端通过唯一的外部访问接口来访问并利用Singleton实例。
饿汉模式单例 & 懒汉模式单例:
饿汉模式(Singleton with Instantiation):
是一种线程安全的实现方法,在类初始化时就完成了单例实例的创建。
懒汉模式(Singleton with Lazy Initialization):
也被称为"双检锁"模式,只有当第一次真正需要获取单例实例时才举行单例实例的创建。
饿汉模式和懒汉模式都实现了单例,即包管在整个应用程序的生命周期中只有一个Singleton类实例。
饿汉模式的优点是线程安全,但缺点是如果该实例很复杂会增长初始化的耗时,从而导致程序的启动时间被延长。
懒汉模式的优点是耽误加载,可以节约资源和减少程序的启动耗时,缺点是需要考虑多线程情况下创建对象导致的线程安全问题,它通常在外部访问接口中利用双重查抄锁定(Double-checked locking)来包管线程安全。
对应UML类图:
三、单例模式代码样例
1.单例模式的伪代码:
- #include <iostream>
- class Singleton {
- private:
- static Singleton* instance;
-
- //私有构造函数,确保不能从外部实例化对象
- Singleton() {}
-
- public:
- //获取单例实例的静态方法
- static Singleton* getInstance() {
- if (instance == nullptr) {
- instance = new Singleton();
- }
- return instance;
- }
- };
- Singleton* Singleton::instance = nullptr;
- int main() {
- Singleton* singleton = Singleton::getInstance();
- return 0;
- }
复制代码 2.单例模式的加锁版伪代码:
- class Singleton {
- private:
- static Singleton* instance;
- Singleton() {} //私有化构造函数,防止外部创建实例
- public:
- static Singleton* getInstance() {
- if (instance == nullptr) {
- //在多线程环境下需要加锁保证只创建一个实例
- // std::lock_guard<std::mutex> lock(mutex);
- instance = new Singleton();
- }
- return instance;
- }
- //单例类的其他成员函数
- void doSomething() {
- // ...
- }
- };
- Singleton* Singleton::instance = nullptr;
- int main() {
- Singleton* obj1 = Singleton::getInstance();
- obj1->doSomething();
- Singleton* obj2 = Singleton::getInstance();
- obj2->doSomething();
- delete obj1; //释放资源
- return 0;
- }
复制代码 3.饿汉模式的伪代码:
- class Singleton {
- private:
- static Singleton* instance;
- //私有构造函数,防止外部直接创建对象
- Singleton() {}
- public:
- //静态成员函数,用于获取单例对象
- static Singleton* getInstance() {
- return instance;
- }
- };
- //提前创建好单例对象
- Singleton* Singleton::instance = new Singleton();
复制代码 4.懒汉模式的伪代码:
- class Singleton {
- private:
- static Singleton* instance;
- Singleton() {}
- public:
- //使用时才创建单例对象
- static Singleton* getInstance() {
- if (instance == nullptr) {
- instance = new Singleton();
- }
- return instance;
- }
- };
复制代码 Demo1:完整代码实现
- #include <iostream>
- class Singleton {
- private:
- static Singleton* instance;
- Singleton() {}
- public:
- static Singleton* getInstance() {
- if (instance == nullptr) {
- instance = new Singleton();
- }
- return instance;
- }
- void showMessage() {
- std::cout << "Hello, World!" << std::endl;
- }
- };
- Singleton* Singleton::instance = nullptr;
- int main() {
- // 获取Singleton对象实例
- Singleton* singleton = Singleton::getInstance();
-
- // 调用对象的方法
- singleton->showMessage();
-
- return 0;
- }
复制代码 运行结果:
Demo2:增长析构函数
- #include <iostream>
- class Singleton {
- public:
- static Singleton& getInstance()
- {
- //如果对象实例不存在就创建一个
- if (!instance) {
- instance = new Singleton();
- }
- return *instance;
- }
- //给外部调用的接口
- void Operation()
- {
- std::cout
- << "Singleton is performing some operation."
- << std::endl;
- }
- Singleton(const Singleton&) = delete;
- Singleton& operator=(const Singleton&) = delete;
- private:
- //私有化的构造函数
- Singleton()
- {
- std::cout << "Singleton instance created."
- << std::endl;
- }
- //私有化的析构函数
- ~Singleton()
- {
- std::cout << "Singleton instance destroyed."
- << std::endl;
- }
- static Singleton* instance;
- };
- Singleton* Singleton::instance = nullptr;
- int main()
- {
- Singleton& singleton = Singleton::getInstance();
- singleton.Operation();
- return 0;
- }
复制代码 运行结果:
- Singleton instance created.
- Singleton is performing some operation.
复制代码 四、单例模式的优缺点
单例模式的优点:
可以有用限制资源的数量,对于那些需要全局访问的资源,单例模式可以包管该资源只有一个实例。
对象的创建/烧毁过程最多只有一次,可以节省系统开销。
可以统一管理全局配置,如果单例模式的对象用来存储一些配置信息,可以实现对全局配置的管理。
简化了访问资源的入口,由于全局只有一个实例,使得客户端只需要关注一个访问入口即可。
单例模式的缺点:
缺乏机动性,一旦创建了单例对象,就不能更改实在例化过程。
限制了一个类只能有一个实例,难以扩展该类的功能。
由于单例对象是全局可访问的,大概引发全局变量的滥用。
存在线程安全隐患,如果不增长一些锁机制,在多线程情况下大概会创建多个实例,影响单例的特性。
五、代码实战
- #include <iostream>
- using namespace std;
- class Singleton
- {
- private:
- static bool instanceFlag;
- static Singleton* single;
- Singleton()
- {
- printf("Private constructor finished.\n");
- }
- public:
- static Singleton* getInstance();
- void method();
- ~Singleton()
- {
- printf("Public de-constructor finished.\n");
- instanceFlag = false;
- }
- };
- bool Singleton::instanceFlag = false;
- Singleton* Singleton::single = NULL;
- Singleton* Singleton::getInstance()
- {
- if (!instanceFlag)
- {
- single = new Singleton();
- instanceFlag = true;
- return single;
- }
- else
- {
- return single;
- }
- }
- void Singleton::method()
- {
- cout << "Method of the singleton class" << endl;
- }
- int main()
- {
- Singleton* sc1, * sc2;
- sc1 = Singleton::getInstance();
- sc1->method();
- sc2 = Singleton::getInstance();
- sc2->method();
- delete sc1, sc2;
- return 0;
- }
复制代码 运行结果:
- Private constructor finished.
- Method of the singleton class
- Method of the singleton class
- Public de-constructor finished.
复制代码 六、参考阅读
https://www.geeksforgeeks.org/singleton-pattern-c-design-patterns/
https://scottlilly.com/c-design-patterns-the-singleton-pattern/
https://www.tutorialspoint.com/explain-cplusplus-singleton-design-pattern
https://www.codeproject.com/Articles/1921/Singleton-Pattern-its-implementation-with-Cplusplu
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |