C++设计模式——Singleton模式
来源:互联网 发布:网络 克隆 编辑:程序博客网 时间:2024/06/06 08:23
一、什么是单例模式:
何为单例模式,在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:保证一个类只有一个实例,并提供一个访问它的全局访问点。首先,需要保证一个类只有一个实例;在类中,要构造一个实例,就必须调用类的构造函数,如此,为了防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为protected或private;最后,需要提供要给全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。
二、单例模式的应用
单例模式:用来创建独一无二的,只能够有一个实例的对象。 单例模式的结构是设计模式中最简单的,但是想要完全实现一个线程安全的单例模式还是有很多陷阱的。单例模式的应用场景:有一些对象其实只需要一个,比如:线程池,缓存,对话框,处理偏好设置和注册表的对象,日志对象,充当打印机,显卡等设备的驱动程序对象。这些对象只能够拥有一个实例,如果创建出了多个实例,就会导致一些程序的问题。程序的行为异常,资源使用的过量,或者导致不一致的结果。常用来管理共享的资源,比如数据库的连接或者线程池。
三、代码实现(c++):
方式一(经典懒汉实现):
#pragma onceclass Singleton{public: static Singleton* Instance(); ~Singleton();private: Singleton(); static Singleton* _instance;};
#include "stdafx.h"#include<iostream>#include "Singleton.h"Singleton* Singleton::_instance = nullptr;Singleton::Singleton(){}Singleton * Singleton::Instance(){ if(nullptr==_instance) { _instance = new Singleton(); } return _instance;}Singleton::~Singleton(){}
#include "stdafx.h"#include"Singleton.h"int main(){ Singleton* sgt = Singleton::Instance(); return 0;}
这是最简单,也是最普遍的实现方式。但是,这种实现方式,有很多问题,比如:没有考虑到多线程的问题,在多线程的情况下,就可能创建多个Singleton实例。(可以想一下在多线程情况下,产生多个Singleton实例的问题,结合C++对象模型,对象内存布局来思考?)
以下版本是改善的版本。
方式二(线程安全懒汉实现):
#pragma once#include<mutex>class Singleton{public: static Singleton* Instance(); ~Singleton();private: Singleton(); static Singleton* _instance; static std::mutex _mutex;};
#include "stdafx.h"#include<iostream>#include "Singleton.h"Singleton* Singleton::_instance = nullptr;std::mutex Singleton::_mutex;Singleton::Singleton(){}Singleton * Singleton::Instance(){ if(nullptr == _instance) { _mutex.lock(); if(nullptr==_instance) { _instance = new Singleton(); } _mutex.unlock(); } return _instance;}Singleton::~Singleton(){}
#include "stdafx.h"#include"Singleton.h"int main(){ Singleton* sgt = Singleton::Instance(); return 0;}
此处进行了两次_instance == nullptr的判断,使用的所谓的“双检锁”机制。因为进行一次加锁和解锁是需要付出对应的代价的,而进行两次判断,就可以避免多次加锁与解锁操作,同时也保证了线程安全。但是,这种实现方法在平时的项目开发中用的很好,也没有什么问题?但是应当注意加锁操作将成为一个性能的瓶颈;为此,一种新的单例模式的实现也就出现了。
方式三(饿汉实现):
#pragma onceclass Singleton{public: static Singleton* Instance(); ~Singleton();private: Singleton(); static Singleton* _instance;};
#include "stdafx.h"#include<iostream>#include "Singleton.h"Singleton* Singleton::_instance = new Singleton();Singleton::Singleton(){}Singleton * Singleton::Instance(){ return _instance;}Singleton::~Singleton(){}
#include "stdafx.h"#include"Singleton.h"int main(){ Singleton* sgt = Singleton::Instance(); return 0;}
因为静态初始化在程序开始时,也就是进入主函数之前,由主线程以单线程方式完成了初始化,所以静态初始化实例保证了线程安全性。在性能要求比较高时,就可以使用这种方式,从而避免频繁的加锁和解锁造成的资源浪费。
方式四(静态局部变量懒汉实现):
#pragma onceclass Singleton{public: static Singleton* Instance(); ~Singleton();private: Singleton();};
#include "stdafx.h"#include<iostream>#include "Singleton.h"Singleton::Singleton(){}Singleton * Singleton::Instance(){ static Singleton _instance; return &_instance;}Singleton::~Singleton(){}
#include "stdafx.h"#include"Singleton.h"int main(){ Singleton* sgt = Singleton::Instance(); return 0;}
其实是使用了C++中成员函数的静态变量的特点:静态局部变量在第一次使用时初始化,并不会销毁直到程序退出。
三、关于懒汉饿汉
可以这样简单粗暴的理解:
- 懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,懒汉么,很懒的,配置文件的实例直到用到的时候才会加载。*
- 饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。
- 设计模式——singleton
- 设计模式——Singleton
- 设计模式——单键模式(singleton)
- 设计模式——单列模式 Singleton
- Singleton模式——设计模式学习
- C++设计模式——Singleton模式
- 设计模式(2)—Singleton模式
- 设计模式—Singleton单件模式
- Singleton设计模式(C++)
- 设计模式——Abstract Factory模式、Singleton模式
- 设计模式1——Singleton设计模式
- 设计模式1——Singleton设计模式
- 设计模式1——Singleton设计模式
- 设计模式——深入浅出单实例Singleton设计模式
- 设计模式-----Singleton模式
- 设计模式-Singleton模式
- 设计模式--Singleton模式
- 设计模式-------Singleton模式
- 史上最清晰的红黑树讲解(上)
- 【RabbitMQ】安装、配置、初体验
- CF 350D 直线映射 + 差分
- 区域的个数 (坐标离散化)
- 基于OC的网络请求
- C++设计模式——Singleton模式
- android上传图片到javaweb服务端,android+和struts2
- laravel 部分静态文件加载需要路由问题(例如字体文件)
- spring 事务管理
- spring中bean的加载
- 每天一个Linux命令(37):wc
- 【Java开发手册之编程规约(六)】并发处理
- View的Draw方法流程
- 常用正则表达式--校验数字