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

来源:互联网 发布:涡流分选器淘宝 编辑:程序博客网 时间:2024/06/14 01:23

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

概述

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例

单例模式的实现大概可以分为懒汉式实现和饿汉式实现。顾名思义,懒汉式就说明它很懒,只有在使用的时候才去创建对象。而饿汉式说明它很饿,还没开始使用就迫不及待的将对象创建出来了。

饿汉式实现

//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_class Singleton{public:  static Singleton* GetInstance(); //公有的获取对象的接口private:  Singleton(){} //私有的构造函数  static Singleton* m_instance;};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = new Singleton();Singleton* Singleton::GetInstance(){  return m_instance;}

饿汉式实现的优缺点

优点

  • 无须担心多线程的问题。

  • 不需要加锁,执行效率比较高

缺点

  • 在类刚加载的时候,就创建了该单例,消耗内存。

懒汉式实现

//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_class Singleton{public:  static Singleton* GetInstance();//公有的获取对象的接口private:  Singleton(){} //私有的构造函数  static Singleton* m_instance;};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = NULL;Singleton* Singleton::GetInstance(){  if (NULL == m_instance)  {    m_instance = new Singleton();  }  return m_instance;}

懒汉式实现优缺点

优点
- 不会在类刚加载的时候就初始化,能节省内存消耗

缺点
- 多线程不安全,必须要通过加锁来保证多线程安全,这样对运行效率有点影响。

懒汉式实现优化

使用加锁来实现懒汉式单例模式.

//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>#include <mutex> //C++11class Singleton{public:  static Singleton* GetInstance();private:  Singleton(){} //私有的构造函数  static Singleton* m_instance;  static mutex m_mutex;  //锁};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = NULL;mutex Singleton::m_mutex;Singleton* Singleton::GetInstance(){  if (NULL == m_instance)  {    std::lock_guard<std::mutex> lock(m_mutex); //在这儿上锁判断,只有多线程访问的时候才会执行上锁解锁,有效的缓解了加锁引起的效率问题。    if (NULL == m_instance)    {      m_instance = new Singleton();          }  }  return m_instance;}

内存释放问题

    说了这么多,关于懒汉式单例模式创建之后的释放问题一直没有解决,我们在第一次初始化的时候创建出来,什么时候去释放它呢?提到这儿,懒汉式单例模式针对资源释放又衍生出了另外的四种实现方式。

1.局部静态变量返回引用实现

#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public:  static Singleton& GetInstance()  {    static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。    return instance;  }private:  Singleton(){} //私有的构造函数};

如此一来,对于单例的释放问题就很简单的解决了,但是如果代码中出现这样使用单例的:

Singleton instance = Singleton::GetInstance();

由于编译器在编译的时候,会自动生成拷贝构造函数,如果这样使用,会调用类的拷贝构造函数,从而制造出另外一个单例对象,这对于单例模式的初衷是矛盾的。因此,针对该问题,有了两种解决办法。

第一种解决办法,也就是懒汉式单例模式实现的第二种方法

2.局部静态变量返回指针实现

#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public:  static Singleton* GetInstance()  {    static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。    return &instance;  }private:  Singleton(){} //私有的构造函数};

这样就解决了调用默认拷贝构造函数引起的问题了。同时还有另外的一种实现,既然是编译器在发现类没实现的时候给默认添加了拷贝构造函数,那我们只需要把拷贝构造函数禁止掉就可以了。所以有了如下实现

3.局部静态变量返回引用,禁止拷贝构造函数实现

#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public:  static Singleton& GetInstance()  {    static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。    return instance;  }private:  Singleton(){} //私有的构造函数  Singleton(const Singleton&);//只声明,不实现  Singleton& operator = (const Singleton&);//只声明,不实现};

这样就有效的避免了在使用单例的时候,无意中调用了拷贝构造函数。当然还有一种高大上的自动释放的实现方式是使用GC机制。

4.使用GC机制的单例实现

class Singleton{public:  static Singleton* GetInstance()private:  class GC  {  public:    ~GC()    {      if (Singleton::m_instance != NULL)      {        delete m_instance;        m_instance = NULL;      }    }    }  static Singleton* m_instance;  static GC gc;};

在使用的时候,必须要声明Singleton::GC:

Singleton::GC Singleton::GC::gc;//必须声明//...//do something//...

如此使用,当你程序结束的时候,就会调用调用GC的析构函数,GC的析构函数会将你的资源释放掉。实现自动释放的功能。

到这儿,五种创建型设计模式已经介绍完了:

1.简单工厂模式(不属于24种设计模式之一)

2.工厂方法模式

3.抽象工厂模式

4.建造者模式

5.原型模式

6.单例模式

原创粉丝点击