Head First 设计模式——单件模式(Singleton Pattern)
来源:互联网 发布:linux裁剪自动化 编辑:程序博客网 时间:2024/06/07 01:01
单件模式(Singleton Pattern)
确保一个类只有一个实例,并提供一个全局访问点
单件模式确保程序中一个类最多只有一个实例。我们在程序中会遇到这种情况如:线程池,缓存,对话框,打印机,显卡等设备驱动程序。这些类对象只能有一个实例,如果制造多个实例,就会导致许多问题产生。
经典的单件模式实现:
#include<iostream>using namespace std;class Singleton{public://用getInstance()方法实例化对象,并返回这个实例static Singleton &getInstance(){if(unique == NULL){unique = new Singleton();cout << "new Singleton" << endl;}return *unique;}static void release(){if (unique != NULL)delete unique;}private://把构造器声明为私有的,只有自Singleton类内//才可以调用构造函数Singleton(){}// 防止外界删除~Singleton(){cout <<" delete Singleton" << endl;}//复制构造函数和= 重载都要保护起来Singleton(const Singleton&);Singleton& operator=(const Singleton&);//利用一个静态变量来记录Singleton类的唯一实例static Singleton *unique;};Singleton * Singleton::unique = NULL;int main(){Singleton::getInstance();Singleton::getInstance();Singleton::release();return 0;}运行结果:
上面是一个比较经典的实现,他的主要问题是——在多线程条件下不能保证只有一个实例被创建,考虑一个下面的执行顺序:
Head First 实例用Java 来实现的,加上自己对C++ 的不是很熟悉,一下内容参考了下面两篇博文
http://www.cnblogs.com/ccdev/archive/2012/12/19/2825355.html
http://blog.yangyubo.com/2009/06/04/best-cpp-singleton-pattern/
在上面的实现中,只有当用户需要用到Instance的时候,程序才会创建一个新的实例,这被称作延迟实例化(对应着“懒汉模式”)
如果应用程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,我们可以急切地创建此单例(对应着“饿汉模式”)
饿汉模式 :
即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并且在以后返回此实例。由静态初始化实例保证其线程安全性,因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心过多的线程问题,故在性能要求较高时,应使用这种模式,避免频繁的锁争夺class Singleton {public: static Singleton* getInstance() { return &m_pInstance; }private: Singleton(){ cout << "new Singleton" << endl; }; // ctor is hidden ~Singleton(){ cout << "delete Singleton" << endl; } Singleton(Singleton const&); // copy ctor is hidden Singleton& operator=(const Singleton&); static Singleton m_pInstance;};// in Singleton.cpp we have to addSingleton Singleton::m_pInstance;
这种模式的问题也很明显, 类现在是多态的, 但静态成员变量初始化顺序还是没保证.
还引起另外一个问题 (我之前碰到过的真实事件, 以后便一直采用下面提到的 "懒汉模式"): 有两个单例模式的类 ASingleton 和 BSingleton, 某天你想在 BSingleton 的构造函数中使用 ASingleton 实例, 这就出问题了. 因为 BSingleton m_pInstance 静态对象可能先 ASingleton 一步调用初始化构造函数, 结果 ASingleton::Instance() 返回的就是一个未初始化的内存区域, 程序还没跑就直接崩掉.
懒汉模式
多线程安全的实现需要用锁,使用double-check来保证thread safety,但是如果处理大量数据时,该锁成为严重的性能瓶颈
1. 静态成员实例的懒汉模式
class Singleton { private: static Singleton* m_instance; Singleton(){} public: static Singleton* getInstance(); }; Singleton* Singleton::getInstance() { if(NULL == m_instance) { Lock();//借用其它类来实现,如boost if(NULL == m_instance) { m_instance = new Singleton; } UnLock(); } return m_instance; }
Instance() 只在第一次被调用时为 m_instance 分配内存并初始化. 看上去所有的问题都解决了, 初始化顺序有保证, 多态也没问题.不过细心的你可能已经发现了一个问题, 程序退出时, 析构函数没被执行. 这在某些设计不可靠的系统上会导致资源泄漏, 比如文件句柄, socket 连接, 内存等等. 幸好 Linux / Windows 2000/XP 等常用系统都能在程序退出时自动释放占用的系统资源. 不过这仍然可能是个隐患, 至少 J. Nakamura 印象中, 有些系统是不会自动释放的.
对于这个问题, 比较土的解决方法是, 给每个 Singleton 类添加一个 destructor() 方法:
virtual bool destructor() { // ... release resource if (NULL!= m_instance) {delete m_instance; m_instance = NULL; }}
然后在程序退出时确保调用了每个 Singleton 类的 destructor() 方法, 这么做虽然可靠, 但却很是繁琐. 幸运的是, Meyers 大师有个更简便的方法.
2. 内部静态实例的懒汉模式
这里需要注意的是,C++ 0x 以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0x 以前仍需加锁。
class Singleton {public: static Singleton& Instance() { //lock() not needed after C++ 0xstatic Singleton instance;return instance;//Unlock() }private:Singleton(){cout << "Singleton" << endl;}; // ctor is hidden~Singleton(){cout <<"~Singleton" << endl;}Singleton(Singleton const&); // copy ctor is hiddenSingleton& operator=(Singleton const&); // assign op is hidden};
int main(){Singleton::Instance();Singleton::Instance();return 0;}
运行结果:
在 Instance() 函数内定义局部静态变量的好处是, instance 的构造函数只会在第一次调用 Instance() 时被初始化, 达到了动态初始化效果, 保证了成员变量和 Singleton 本身的初始化顺序.
它还有一个潜在的安全措施, Instance() 返回的是对局部静态变量的引用, 如果返回的是指针,Instance() 的调用者很可能会误认为他要检查指针的有效性, 并负责销毁. 构造函数和拷贝构造函数也私有化了, 这样类的使用者不能自行实例化.
另外, 多个不同的 Singleton 实例的析构顺序与构造顺序相反.
- Head First 设计模式——单件模式(Singleton Pattern)
- Head First 设计模式 (五) 单件模式(Singleton pattern) C++实现
- Head First 设计模式之单件模式(Singleton Pattern)
- Head First设计模式 C++实现-Singleton(单件模式)
- <Head First 设计模式>:单件模式:Singleton
- 设计模式——单件模式(Singleton Pattern)
- head first 设计模式——(单件模式)
- 设计模式-单件模式(Singleton Pattern)
- 《Head First 设计模式》单件模式
- Head First-设计模式:单件模式
- 单件模式——Singleton Pattern
- 《Head First Design Patterns》笔记五:单件模式(Singleton Pattern)
- 设计模式—Singleton单件模式
- Head First设计模式C++实现--第五章:单件(Singleton)模式
- 【设计模式】《Head First 设计模式》读书笔记——单件模式
- Head First 设计模式 —— 单例模式(Singleton)
- Head First 设计模式 Design Pattern 5-6 Singleton, Command
- Head First设计模式 读书笔记-单件模式、命令模式
- java-----------Jackson 框架,轻易转换JSON
- linux查看端口占用情况
- 存储系统实现-构建自己的存储系统(一)
- android之字体阴影效果 [复制链接]
- 转十大排序算法
- Head First 设计模式——单件模式(Singleton Pattern)
- INI配置文件的格式
- java------------形参中的点点点
- java锁机制
- SVM算法入门
- MySQL云数据库服务的架构探索
- Linux 下查看系统是32位 还是64 位的方法
- Spring MVC学习(七)-------SpringMVC数据格式化
- JAVA---------------String,StringBuffer与StringBuilder的区别??