C++设计模式——Singleton单例模式

发布时间:2024-11-25 07:30

设计模式在编程中的应用:工厂模式实例 #生活知识# #编程教程#

一、单例模式的定义  

单例模式,英文全称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) {

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::getInstance();

singleton->showMessage();

return 0;

}

运行结果:

Hello, World!

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

网址:C++设计模式——Singleton单例模式 https://www.yuejiaxmz.com/news/view/253737

相关内容

C++ 设计模式之策略模式
23种设计模式总结及应用场景
设计模式生活实例
【设计模式】代理模式
【设计模式】策略模式 ( 简介
策略模式(Strategy Pattern):电商平台的优惠券系统实战案例分析
【设计模式】状态模式 ( 简介
设计模式第11讲——外观模式(Facade)
设计模式第14讲——享元模式(Flyweight)
【设计模式】解释器模式 ( 简介

随便看看