C++ 设计模式 之 单例模式

2020-09-09  本文已影响0人  Aliven888

文档声明:
以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正。并且该文档在后期会随着学习的深入不断补充完善。


资料仅供学习交流使用。
作者:Aliven888

1、背景

1.1、为什么要学习设计模式

设计模式是一种知识和经验,和编程语言无关。熟练的掌握各种设计模式后,我们(程序猿)可以快速的去识别一个系统的骨骼框架,也可以快速的搭建出一个健壮的系统。

设计模式也可以理解为我们(程序猿)心中的一张张蓝图,握住他们,就可能成为一位有大局观的构架师,松开它们,可能注定只能成为一名默默无闻 的码农。

1.2、什么是单例模式

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式,,可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。

如果希望在系统中某个类的对象只存在一个,单例模式显然是最好的解决方案。

1.3、单例模式的特点

1、某个类只有一个实例(并非绝对,一些特殊的情况下可以存在多个)。
2、它必须自行创建这个实例。
3、它必须向整个系统提供这个实例(即整个系统都可以直接使用该实例)。

1.4、使用场景

1、日志打印:每一个软件系统都会存在一个日志打印功能,而且在软件系统中很多位置都在调用该打印功能,此时为了保证日志文件的安全写入,可以使用单例模式实现。

2、设备管理系统:在设备管理系统中,不管有多少个设备,那么设备的管理类就只会存在一个。

1.5、单例模式的实现思路

要求类只能返回同一个对象的引用,和一个获取给对象的方法。

单例模式的实现主要分为以下两个步骤:

1、将该类的构造方法定义为私有方法,这样其他的代码就无法调用该构造函数去实例化新的对象了。

2、该类提供一个静态的方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,否则就先创建,然后再返回。

1.6、单例模式的UML:

在这里插入图片描述

1.7、单例模式常用的实现方式

1、懒汉模式
2、线程安全模式
3、饿汉模式

2、单例模式常用模式介绍

2.1、懒汉模式

定义: 懒汉,顾名思义,就是很懒,不到使用的时候,是不会想起来去实例化它的。也就是说在第一次使用到类实例的时候才回去实例化。

特点: 以空间换时间,是非线程安全的。

懒汉模式代码演示:

//.h
class CSingletonPattern
{
public:
    static CSingletonPattern *getInstance();  //创建实例对象接口函数
    void DestoryInstance();  //销毁实例对象接口函数

    ~CSingletonPattern();

private:
    CSingletonPattern();

private:
    static CSingletonPattern *m_instance;
};


//.cpp
CSingletonPattern::CSingletonPattern()
{
}

CSingletonPattern::~CSingletonPattern()
{
    //销毁对象
    DestoryInstance();
}

//初始化对象
CSingletonPattern *CSingletonPattern::m_instance = NULL;

 //创建实例对象
CSingletonPattern* CSingletonPattern::getInstance() 
{
    //对象不为空,则创建对象
    if (NULL == m_instance)
    {
        m_instance = new CSingletonPattern();
    }
    return m_instance;
}
void CSingletonPattern::DestoryInstance()  //销毁实例对象
{
    delete m_instance;
    m_instance = NULL;
}

2.2、线程安全模式

我们前面说懒汉模式在线程上是不安全的,那我要怎么实现呢?
相比想到这里就行明白了,既然线程资源不安全,那么我们就加个线程锁控制一下如何。

代码演示:

//.h
class CSingletonPattern
{
public:
    static CSingletonPattern *getInstance();  //创建实例对象
    void DestoryInstance();  //销毁实例对象

    ~CSingletonPattern();

private:
    CSingletonPattern();

private:
    static CSingletonPattern *m_instance;
    static mutex m_mutex;  //定义互斥锁
};

//.cpp
CSingletonPattern::CSingletonPattern()
{
}

CSingletonPattern::~CSingletonPattern()
{
    DestoryInstance();
}

//初始化对象
CSingletonPattern *CSingletonPattern::m_instance = NULL;
mutex CSingletonPattern::m_mutex;

CSingletonPattern* CSingletonPattern::getInstance()  //创建实例对象
{
    //对象不为空,则创建对象
    if (NULL == m_instance)
    {
        m_mutex.lock();
        //这个为了防止在加锁的过程中,系统中的两个位置同时调用,这里需要在判断一次
        //以保证加锁成功后进来的只有一个位置调用。
        if(NULL == m_instance)
        {
            m_instance = new CSingletonPattern();
        }
        m_mutex.unlock();
    }
    return m_instance;
}
void CSingletonPattern::DestoryInstance()  //销毁实例对象
{
    delete m_instance;
    m_instance = NULL;
}

2.3、饿汉模式

定义: 顾名思义,饿的时候才会饥不择食。在系统启动时,对象就被实例化创建。

特点: 以空间换时间,是线程安全的。

//.h
class CSingletonPattern
{
public:
    static CSingletonPattern *getInstance();  //创建实例对象接口函数
    void DestoryInstance();  //销毁实例对象接口函数

    ~CSingletonPattern();

private:
    CSingletonPattern();

private:
    static CSingletonPattern *m_instance;
};


//.cpp
CSingletonPattern::CSingletonPattern()
{
}

CSingletonPattern::~CSingletonPattern()
{
    //销毁对象
    DestoryInstance();
}

//初始化对象
CSingletonPattern *CSingletonPattern::m_instance = new CSingletonPattern();

 //获取实例对象
CSingletonPattern* CSingletonPattern::getInstance() 
{
    return m_instance;
}
void CSingletonPattern::DestoryInstance()  //销毁实例对象
{
    delete m_instance;
    m_instance = NULL;
}

2.4、优缺点对比

1、懒汉方式:在访问量较少的情况下使用,以时间换空间,但是线程不安全。

2、饿汉方式:在访问量较多的情况下使用,以空间换时间,线程安全;

3、饿汉方式反而是最懒的。

上一篇 下一篇

猜你喜欢

热点阅读