实现类的单个案件的Singleton模式。该系统有一个类只有一个实例,而本实施例是容易的外部访问。所以容易控制的实例的数量,并且节省系统资源。

单的情况下通常与一些非本地静态对象的使用,对于这些对象,计划是难以控制。对于那些具有全球影响,持久对象和一般的存在,根据某些约束有时需要被初始化或顺序,始化这些对象假设不使用单例方法的话会极度不安全。这个时候就要使用单例模式来解决问题。

实现单例的方法有非常多,最简单的一个是将对象放入函数中作为其静态成员:

class SingleTon;
SingleTon* getSingleTonInstance(){
static SingleTon* instance = new SingleTon();
return instance;
}
class SingleTon{
friend SingleTon* getSingleTonInstance();
private:
SingleTon(){}
};

这是我觉得的最简单的实现单例模式的方法,不足的地方在于这个获得单例对象的函数不在类内。

首先要实现单例模式,将构造函数声明为稀有。这样构造函数就不能被方法,也不能任意创建单例类的对象。而这里获得实例为函数的静态对象,所以其仅仅有一个。且存在时间为创建到程序结束。

当然。也能够将函数中的静态对象改为类中的静态对象,而将这个全局的函数设置为类中的静态函数,这样就得到一个更加普遍经常使用的形式:

class SingleTon{
public:
static SingleTon* getInstance(){
static SingleTon* instance = new SingleTon();
return instance;
}
~SingleTon(){}
private:
SingleTon(){ }
SingleTon(const SingleTon&);
SingleTon& operator=(const SingleTon&);
};

这里还是使用了函数中的静态成员,使用类中的静态成员也是能够的:

class SingleTon{
public:
static SingleTon* getInstance(){
if(NULL == instance)
instance = new SingleTon();
return instance;
} private:
SingleTon(){ }
SingleTon(const SingleTon&);
SingleTon& operator=(const SingleTon&);
static SingleTon* instance;
};
SingleTon* SingleTon::instance;// = new SingleTon();类内的静态成员初始化能够调用类中的私有的构造函数。

为了安全性,这里将复制构造函数和赋值操作符都给隐藏了。可是析构函数还是可见的,程序猿还是会误用delete来删除这个单例实体,这样是不安全的,能够选择将析构函数放入私有中。隐藏析构函数,对于一些对象在最后结束时析构。则不用关心其释放过程。

可是假设在程序运行中要调用析构函数进行实例的删除的话,就使用一个公有的函数来封装析构函数,且将析构函数置为私有:

class SingleTon{
public:
static SingleTon* getInstance(){
if(NULL == instance)
instance = new SingleTon();
return instance;
}
static void delelteInstance(){
if(NULL != instance){
delete instance;
instance = NULL;
}
}
private:
SingleTon(){ }
SingleTon(const SingleTon&);
SingleTon& operator=(const SingleTon&);
static SingleTon* instance;
~SingleTon();
};
SingleTon* SingleTon::instance ;

这里就已经基本上在单线程上安全了,然后就考虑多线程。当多个线程企图同一时候初始化 单例实例时,就出现了问题,要使用相互排斥来解决这个问题。这里就使用临界区来解决:

CRITICAL_SECTION cs;
class SingleTon{
public:
static SingleTon* getInstance(){
if(NULL == instance){
EnterCriticalSection(&cs);
if(NULL == instance){//双检锁。在进入临界区后再检測一次是否对象已经建立
instance = new SingleTon();
}
LeaveCriticalSection(&cs);
}
return instance;
}
static void delelteInstance(){
if(NULL != instance){
EnterCriticalSection(&cs);
if(NULL != instance){
delete instance;
instance = NULL;
}
LeaveCriticalSection(&cs);
}
}
private:
SingleTon(){ }
SingleTon(const SingleTon&);
SingleTon& operator=(const SingleTon&);
static SingleTon* instance;
~SingleTon();
};
SingleTon* SingleTon::instance ;

这里使用双检锁的机制,第一次是推断是否须要对实例进行操作,第二次是在进入临界区即对数据加锁后,推断在数据已经不会再被外界干扰的情况下。第一次推断和第二次推断之间是否被其它线程进行了操作,这样两次推断保证了实例的安全。

可是这样还是不够安全。由于多线程中还是会有一些特殊情况,在类中一些文件被锁了,如文件句柄,数据库连接等,这些随着程序的关闭并不会马上关闭资源。必需要在程序关闭前,进行手动释放。

这里的指不会自己主动关闭。是对于析构函数是私有的情况下,由于系统无法訪问私有的析构函数。对于没有这些连接时。即类仅仅在内存中占领了一些地址,则系统将其视为全局变量。在结束时释放其所在内存资源,所以没有内存泄漏。而若类中有文件句柄和数据库连接这些东西。系统并不会帮忙关闭这些。所以必须手动的调用析构函数中对这些文件的关闭操作。

对于这种情况,通常会使用一种私有内嵌类Garbo,意为垃圾工人。在单例类中包括一个私有的静态垃圾工人对象,当程序结束时。系统会调用这个对象的析构函数,而这个析构函数中对单例类对象实现析构。

CRITICAL_SECTION cs;
class SingleTon{
public:
static SingleTon* getInstance(){
if(NULL == instance){
EnterCriticalSection(&cs);
if(NULL == instance){//双检锁。在进入临界区后再检測一次是否对象已经建立
instance = new SingleTon();
}
LeaveCriticalSection(&cs);
}
return instance;
}
static void delelteInstance(){
if(NULL != instance){
EnterCriticalSection(&cs);
if(NULL != instance){
delete instance;
instance = NULL;
}
LeaveCriticalSection(&cs);
}
} private:
SingleTon(){ }
SingleTon(const SingleTon&);
SingleTon& operator=(const SingleTon&);
static SingleTon* instance;
~SingleTon(){}//对应的关闭连接等操作
class GarBo{
public:
~GarBo(){
if(NULL != instance){
EnterCriticalSection(&cs);
if(NULL != instance){
delete instance;
instance = NULL;
}
LeaveCriticalSection(&cs);
}
}
};
static GarBo gc ;
};
SingleTon* SingleTon::instance ;
SingleTon::GarBo SingleTon::gc;//类外的初始化。

这样就得到更加完美的单例类。

版权声明:本文博主原创文章,博客,未经同意不得转载。

设计模式C++达到 1.辛格尔顿的更多相关文章

  1. 【从cocos2d-x学习设计模式】第一阶段:辛格尔顿

    设计模式,它总结了前辈在许多方案重用代码.它是一个想法. 因为我们爱cocos2d-x,然后我们从去cocos2d-x在设计模式中,右一起学习!本篇解释未来辛格尔顿. 提cocos2d-x中间Dire ...

  2. 设计模式——辛格尔顿(Singleton)

    要想正确理解设计模式,首先必须明白它是为了解决什么问题而提出来的. 设计模式学习笔记 --Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 单例模式属于设计模式 ...

  3. 【OC加强】辛格尔顿和[NSFileManager defaultMagager]以及其他设计模式

    我们在工作中使用文件NSFileManager上课时间,创建发现1对象,此2同样的对象地址: NSFileManager *file1=[NSFileManager defaultManager]; ...

  4. Javascript 设计模式 辛格尔顿

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/30490955 我一直很喜欢Js,,,今天写JsSingleton模式来实现,以及 ...

  5. JAVA设计模式--辛格尔顿

    Singleton模式可以作为一种编程技术,让我们先从理论上说代码 单例模式三个关键点: 1).某个类仅仅能有一个实例 2).该类必须自行创建这个实例 3).该类必须自行向整个系统提供这个实例 应用场 ...

  6. 我学的是设计模式的视频教程——辛格尔顿,生成器VS工厂方法

    课程视频 单例模式         建造者VS工厂方法                      课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 版权声明:本文博客原创文章,博客, ...

  7. Swift辛格尔顿设计模式(SINGLETON)

    本文已更新为2.0语法,具体查看:一叶单例模式 一.意图 保证一个类公有一个实例.并提供一个訪问它的全局訪问点. 二.使用场景 1.使用场景 当类仅仅能有一个实例并且客户能够从一个众所周知的訪问点訪问 ...

  8. iOSSingleton设计模式详细的说明教程

    iOS有很多的设计模式,当然,不管是什么语言有很多的设计模式.辛格尔顿是一种之一,辛格尔顿,它从字面上是一个单独的实例,首先,它是只有一个单一的,其次,它是一个实例.我们知道,在iOS用于开发Obje ...

  9. 辛格尔顿和Android

    辛格尔顿(Singleton) .singleton.h,定义类的基本成员及接口 #ifndef SINGLETON_H_INCLUDE #define SINGLETON_H_INCLUDE cla ...

随机推荐

  1. poj 2201 构造

    这个题目的构造方法应该还算是很好想的,先给a按照从小到大排序,然后按顺序插入数据,构造一棵二叉查找树,而且50000的数据,nlogn的做法,应该还是很好的.不过这个题目的编码比想象中要麻烦一点,并且 ...

  2. 内存级别/栅栏 ( Memory Barriers / Fences ) – 翻译

    翻译自:Martin Thompson – Memory Barriers/Fences 在这篇文章里,我将讨论并发编程里最基础的技术–以内存关卡或栅栏著称.那让进程内的内存状态对其它进程可见. CP ...

  3. java--基于socket的网络传输开发

    继http://blog.csdn.net/gaopeng0071/article/details/10959845此文章内容展开的研究. socket传输是基于tcp的网络传输协议进行的传输,tcp ...

  4. "ScrollView can host only one direct child"问题解决了

    1. 问题叙述性说明: (请注意以下几点大胆). ScrollView作为顶层view时报错,直接导致apk崩溃.具体错误信息例如以下: 12-21 09:12:15.150: D/AndroidRu ...

  5. js:进一步关闭(范围:下一个)

    function fn1(){   //创建一个数组   var fns = new Array();   //i这个变量是保存在fn1这个作用域中   for(var i=0;i<10;i++ ...

  6. 网格最短路径算法(Dijkstra & Fast Marching)(转)

    Dijkstra算法是计算图中节点之间最短路径的经典算法,网上关于Dijkstra算法原理介绍比较多,这里不再多讲.值得一提的是,当图中节点之间的权重都为1时,Dijkstra算法就变化为一般意义上的 ...

  7. hdu4126(最小生成树+dfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4126 题意:给出一幅3000个点的图,有10000次操作: 求将某条边的权值变大后的最小生成树,最后输 ...

  8. •当对自己的技术足够自信的时候,拼的就是RP和面试技巧了(转)

    前言 三月真是一个忙碌的季节,刚刚开学就需要准备各种面试和笔试(鄙视).幸运的是,在长达一个月的面试内推季之后,终于同时拿到了阿里和腾讯的offer,还是挺开心的.突而想起久未更新的博客,就冒昧学一学 ...

  9. Git双机同步

    如果使用git init 初始化,当客户端仓库push内容时,服务器端仓库可以看到log,但是更新的文件不能显示,必须使用git reset --hard才能更新内容

  10. lightoj1027(期望dp)

    有一个迷宫,有n个门,走每个的概率都是相同的 每个门有一个数字,如果是正数ai,那么表示走ai天就能走出迷宫,如果是负数,那么走-ai天会回到原地,然后会忘记之前的事情,继续选择门去走 所以,如果都是 ...