设计模式----单例模式

单例模式

只生成一个对象实例,减少了系统的开销;方便数据访问。

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

系统中如果一个类仅有一个实例,可以用来存储数据。全局访问

单例实现

1、将该类的构造方法定义为私有方法,这样其他处代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

2、在该类中提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。

懒汉式模式

不加锁

顾名思义,不到万不得已不去实例化类,也就是说在第一次用到实例的时候才回去实例化。

在访问量较小时,采用懒汉式实现。这是以时间换空间。

复制代码
class Singleton1
{
public:
    static Singleton1 *GetInstance()
    {
        if (instance == NULL)
        {
           instance = new Singleton1();
           return instance;
        }
    }
private:
    Singleton1(){};
    Singleton1(const Singleton1&){};//禁止拷贝
    Singleton1& operator = (const  Singleton1&){};//禁止赋值
    static Singleton1 *instance;
};

Singleton1* Singleton1::instance = NULL;

在懒汉模式下,再定义instance时先等于NULL,在调用GetInstance()方法时,在判断是否要赋值。这种模式下,并非是线程安全的,因为多个线程同时调用GetInstance()方法,就可能导致产生多个实例。要实现线程安全,就必须加锁。

加锁

复制代码
class Singleton
{
private:
    Singleton(){
        pthread_mutex_init(&mutex);    
    };
    Singleton(const Singleton&){};
    Singleton& operator=(const Singleton&){};
    static Singleton* instance;
public:
    static pthread_mutex_t mutex;
    static Singleton* GetInstance();
};


pthread_mutex_t Singleton::mutex;
Singleton* Singleton::instance = NULL;


Singleton* Singleton::GetInstance(){
    if(instance == NULL){
          pthread_mutex_lock(&mutex);
          if(instance == NULL)
              instance = new Singleton();
          pthread_mutex_unlock(&mutex);
      }
      return instance;
}

饿汉式模式

线程安全:还未使用变量时,已经对instance进行赋值,就像很饥饿的感觉。在多线程环境下肯定是线程安全的,因为不存在多线程实例化的问题。

复制代码
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        return instance;
    }
private:
    Singleton();
    Singleton(const Singleton&){};
    Singleton& operator=(const Singleton&){};
    static Singleton *instance;
};

Singleton *Singleton::instance = new  Singleton();

饿了肯定就会饥不择食,所以在单例类定义的时候就进行实例化。

由于要进行线程同步,所以在访问量比较大或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

单例模式的优点

1、 在内存中只有一个对象,节省内存空间。

2、 避免频繁的创建销毁对象,可以提高性能。

3、 避免对共享资源的占用。

4、 可以全局访问。

适应的场景

1、 需要频繁实例化然后销毁的对象。

2、 创建对象耗时过多或者耗资源过多,但又经常用到的对象。

3、 有状态的工具类对象。

4、 频繁访问数据库或文件的对象。

5、 以及其他要求只有一个对象的场景。

注意

1、 实例控制 :单例模式会阻止其他对象实例化自己的单例对象的副本,从而确保所有对象都访问唯一实例。

2、 灵活性 :因为类控制实例化过程,所以类可以灵活更改实例化过程。

3、 开销:虽然数量很少,但如果每一次对象请求引用时,都要检查是否存在类的实例,仍然需要一些开销,这个问题可以通过静态初始化解决此问题。定义一个私有的静态指针instance,和一个公有的静态函数GetInstance()。

相关推荐
长按助力退休2 小时前
设计模式实战,这 5 个最常用
设计模式
Carl_奕然4 小时前
【智能体】Agent的四种设计模式之:Multi-Agent Collaboration
设计模式
Lost of 程序猿4 小时前
建造者模式实战:告别“十参数构造函数“的数据导出任务
后端·设计模式·c#·asp.net
SL_staff4 小时前
合规性折旧:当知识资产因主权缺位在审计中‘功能性清零’
java·设计模式·开源
Zane19948 小时前
工厂方法一定比简单工厂高级?三种工厂模式到底该怎么选
设计模式
Hespethorn9 小时前
设计模式是语言缺陷的补丁 —— 从工厂、单例、策略三个模式说起
设计模式
Lost of 程序猿9 小时前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式
一只旭宝9 小时前
【C++复习】四种类型转换 + 常见设计模式 + Redis/MySQL(后端面试复习完整版)
c++·redis·笔记·mysql·设计模式
YYYing.11 小时前
【设计模式系列 (四) 】建造者模式
c++·后端·设计模式·建造者模式·c/c++
Zane19941 天前
同一段单例代码,为什么在高并发下偶尔会创建出两个实例?聊聊哪种单例实现才是真的安全
设计模式