单件模式,如何灵活应付单例的生命周期。
2014-05-11 12:44
169 查看
开始复习设计模式,第一个,单件模式。
我想我要写的东西太长了,于是我打算说我解决了什么问题,基础足够的同学请自行补脑。
单件模式为解决复杂系统只需要一个实例的问题。但是没有提在C++里面怎么解决内存自动释放的问题。
我相信大多数人首先想到的C++实现都单纯的类似这样:
class Singleton
{
public:
~Singleton(){}
static Singleton* Instance()
{
if (_instance == NULL)
{
_instance = new Singleton();
}
return _instance;
}
private:
Singleton(){}
static Singleton* _instance;
};
Singleton* Singleton::_instance = NULL;
这个确实是单件模式了,但是它没有解决单例的生命周期问题,new出来的内存没有delete掉,那么这个对象的生命到底什么时候结束呢?
答案不是确定的,在不同的操作系统平台上又不同的情况。Unix下是进程消失时内存释放。
我们来解决这个问题,给它加一个清理器。嘿嘿!~~
为了更加通用,我打算用模板来实现,请看代码:
// singleton.h
#ifndef __SINGLETON__
#define __SINGLETON__
#include <iostream>
template<typename T>
class Singleton {
public:
static T *instance(){
if (_instance == nullptr) { //clang++ c++11标准
_instance = new T;
static Cleaner clr; //延迟单件模式的清理对象
/*
static Cleaner clr;这个声明,由于是静态成员,系统会在栈里分配内存,回收工作也就由系统自动完成了。
*/
}
return _instance;
}
private:
Singleton(){
}
Singleton(const Singleton &s){};
void operator=(const Singleton &rhs){};
static T *_instance;
class Cleaner {
public:
Cleaner(){
std::cout<<"Singleton cleaner Construct"<<std::endl;
}
~Cleaner(){
std::cout<<"Singleton cleaner Deconstruct"<<std::endl;
if(Singleton<T>::instance()) {
delete Singleton::instance();
}
}
};
};
template<typename T> T * Singleton<T>::_instance = nullptr;
#endif
那么我们来使用一下:
#include <iostream>
#include "singleton.h"
typedef class aClass{
//整个函数可以注释掉
public:
void Print(const char* str){
std::cout << "aClass print:" << str;
std::cout<<", my address is " << this << std::endl;
}
~aClass(){
std::cout<<"aClass Deonstruct"<<std::endl; //可以注释
}
aClass(){
std::cout<<"aClass Construct"<<std::endl; //可以注释
}
}aClass;
void f(){
Singleton<aClass >::instance()->Print("print 1");
Singleton<aClass >::instance()->Print("print 2");
}
int main(){
f();
return 0;
}
这样解决了单件模式自动释放的问题。
原理是什么呢?
在instance中,static
Cleaner clr;这个声明,由于是静态成员,系统会在栈里分配内存,回收工作也就由系统自动完成了。
有时候我们要考虑单件在整个软件系统中的释放顺序,因此,
如果您还有兴趣,我们可以看一下这个单例的释放究竟是在什么时候:
#include <vector>
#include "singleton.h"
typedef class aClass{
//整个函数可以注释掉
public:
void Print(const char* str){
std::cout << "aClass print:" << str;
std::cout<<", my address is " << this << std::endl;
}
~aClass(){
std::cout<<"aClass Deonstruct"<<std::endl; //可以注释
}
aClass(){
std::cout<<"aClass Construct"<<std::endl; //可以注释
}
}aClass;
void f(){
Singleton<aClass >::instance()->Print("print 1");
Singleton<aClass >::instance()->Print("print 2");
}
class bClass{
public:
bClass(){
std::cout<<"bClass Construct"<<std::endl;
}
~bClass(){
std::cout<<"bClass Deconstruct"<<std::endl;
}
}globalObject;
class cClass{
public:
cClass(){
std::cout<<"cClass Construct"<<std::endl;
}
~cClass(){
std::cout<<"cClass Deconstruct"<<std::endl;
}
};
int main(){
cClass c;
f();
Singleton<aClass >::instance()->Print("print 2");
return 0;
}
根据在MAC下的控制台的输出结果:
clang++ -std=c++1y main.cpp && ./a.out
bClass Construct
cClass Construct
aClass Construct
Singleton cleaner construct
aClass print:print 1, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
cClass Deconstruct
Singleton cleaner deconstruct
aClass Deonstruct
bClass Deconstruct
我们可以看出,这个单件模式的实例的释放时机为:在main退出之后,在全局对象析构之前。(也就是说它的释放时机是和系统的栈内存一样的。)
最后有人会问,你这个没有考虑多线程下的问题。
是的,不过这也简单,我们为instance函数添加互斥条件就可以了。多线程的例子,我在后面在写。
谢谢参观!
我想我要写的东西太长了,于是我打算说我解决了什么问题,基础足够的同学请自行补脑。
单件模式为解决复杂系统只需要一个实例的问题。但是没有提在C++里面怎么解决内存自动释放的问题。
我相信大多数人首先想到的C++实现都单纯的类似这样:
class Singleton
{
public:
~Singleton(){}
static Singleton* Instance()
{
if (_instance == NULL)
{
_instance = new Singleton();
}
return _instance;
}
private:
Singleton(){}
static Singleton* _instance;
};
Singleton* Singleton::_instance = NULL;
这个确实是单件模式了,但是它没有解决单例的生命周期问题,new出来的内存没有delete掉,那么这个对象的生命到底什么时候结束呢?
答案不是确定的,在不同的操作系统平台上又不同的情况。Unix下是进程消失时内存释放。
我们来解决这个问题,给它加一个清理器。嘿嘿!~~
为了更加通用,我打算用模板来实现,请看代码:
// singleton.h
#ifndef __SINGLETON__
#define __SINGLETON__
#include <iostream>
template<typename T>
class Singleton {
public:
static T *instance(){
if (_instance == nullptr) { //clang++ c++11标准
_instance = new T;
static Cleaner clr; //延迟单件模式的清理对象
/*
static Cleaner clr;这个声明,由于是静态成员,系统会在栈里分配内存,回收工作也就由系统自动完成了。
*/
}
return _instance;
}
private:
Singleton(){
}
Singleton(const Singleton &s){};
void operator=(const Singleton &rhs){};
static T *_instance;
class Cleaner {
public:
Cleaner(){
std::cout<<"Singleton cleaner Construct"<<std::endl;
}
~Cleaner(){
std::cout<<"Singleton cleaner Deconstruct"<<std::endl;
if(Singleton<T>::instance()) {
delete Singleton::instance();
}
}
};
};
template<typename T> T * Singleton<T>::_instance = nullptr;
#endif
那么我们来使用一下:
#include <iostream>
#include "singleton.h"
typedef class aClass{
//整个函数可以注释掉
public:
void Print(const char* str){
std::cout << "aClass print:" << str;
std::cout<<", my address is " << this << std::endl;
}
~aClass(){
std::cout<<"aClass Deonstruct"<<std::endl; //可以注释
}
aClass(){
std::cout<<"aClass Construct"<<std::endl; //可以注释
}
}aClass;
void f(){
Singleton<aClass >::instance()->Print("print 1");
Singleton<aClass >::instance()->Print("print 2");
}
int main(){
f();
return 0;
}
这样解决了单件模式自动释放的问题。
原理是什么呢?
在instance中,static
Cleaner clr;这个声明,由于是静态成员,系统会在栈里分配内存,回收工作也就由系统自动完成了。
有时候我们要考虑单件在整个软件系统中的释放顺序,因此,
如果您还有兴趣,我们可以看一下这个单例的释放究竟是在什么时候:
#include <vector>
#include "singleton.h"
typedef class aClass{
//整个函数可以注释掉
public:
void Print(const char* str){
std::cout << "aClass print:" << str;
std::cout<<", my address is " << this << std::endl;
}
~aClass(){
std::cout<<"aClass Deonstruct"<<std::endl; //可以注释
}
aClass(){
std::cout<<"aClass Construct"<<std::endl; //可以注释
}
}aClass;
void f(){
Singleton<aClass >::instance()->Print("print 1");
Singleton<aClass >::instance()->Print("print 2");
}
class bClass{
public:
bClass(){
std::cout<<"bClass Construct"<<std::endl;
}
~bClass(){
std::cout<<"bClass Deconstruct"<<std::endl;
}
}globalObject;
class cClass{
public:
cClass(){
std::cout<<"cClass Construct"<<std::endl;
}
~cClass(){
std::cout<<"cClass Deconstruct"<<std::endl;
}
};
int main(){
cClass c;
f();
Singleton<aClass >::instance()->Print("print 2");
return 0;
}
根据在MAC下的控制台的输出结果:
clang++ -std=c++1y main.cpp && ./a.out
bClass Construct
cClass Construct
aClass Construct
Singleton cleaner construct
aClass print:print 1, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
cClass Deconstruct
Singleton cleaner deconstruct
aClass Deonstruct
bClass Deconstruct
我们可以看出,这个单件模式的实例的释放时机为:在main退出之后,在全局对象析构之前。(也就是说它的释放时机是和系统的栈内存一样的。)
最后有人会问,你这个没有考虑多线程下的问题。
是的,不过这也简单,我们为instance函数添加互斥条件就可以了。多线程的例子,我在后面在写。
谢谢参观!
相关文章推荐
- 如何在XP系统中设置Win7才有的离开模式(应付下载)
- 2.2 《硬啃设计模式》 第4章 如何管理全局信息?- 单件模式(Singleton Pattern)
- 如何在MVP模式中控制RxAndroid的生命周期?
- 关于activity的启动模式问题,生命周期和TabActivity是如何做到视图切换的
- C++中如何实现单件模式
- .NET设计模式(2):单件模式(Singleton Pattern)
- 如何实现servlet得单线程模式
- CDB重启时如何保持PDB的open模式(文档 ID 1933511.1)
- 设计模式 之 单件模式
- 设计模式(二)单件模式Singleton(创建型)
- 如何使用 Java8 实现观察者模式?(上)
- 如何修改SQLServer2000身份验证模式和系统管理员
- 如何应付全英文的技术面试(一)
- 设计模式-单件模式(Singleton)
- branches&tags&trunk模式下如何建svn库
- DB 查询分析器 6.03 如何灵活、快捷地操作国产达梦数据库
- 如何利用神经网络和Python生成指定模式的密码
- 如何使用apache的 work模式还是 prefork 模式
- 如何应用DISC行为模式测评进行岗位(职位)匹配?
- 如何使用VIM的列编辑模式 [转]