5 单实例类

5.1 缘由

单实例类,其作用类似于全局变量,实现的方法有很多,CEF3的一些代码中就直接使用的全局变量,不过这个全局变量是在一个未命名的namespace里面定义的.Loki库里面也对单件模式也有非常翔实的描述,但是那个太多,太大,我个人觉得反而将单实例类的概念淹没了.

试想一下,如果实现一个通用的单实例设备出来,通过引用这个设备,我们就可以方便的生产出单实例类.碰到这种问题我们首先的想法就是:构造一个基类,这个基类中有一个用于指代单实例子类的静态指针成员,还有一些静态函数.但事实上是,一旦你这样去做会碰到很多的问题,导致根本无法实行我们的想法.

到这里,如果没有别的想法,我们肯定又会投向Marco的怀抱了.但是这次不一样了,我们有了新的解决方案,比宏更好用,而且有绝佳的正交性.

5.2 源码及说明

其实这里,我们还是沿用了我们最初的想法,我们又通过模板的使用克服了这个想法中的重重难关,使之成为现实:

<文件:Fade\Singleton\Singleton.h>

/************************************************************************
Author:Tanglx
Date:2017/10/12
FileName:Singleton.h
Describe:
************************************************************************/
#ifndef _FADE_SINGLETON_
#define _FADE_SINGLETON_
template<class _ty>
class CSingleton{
protected:
	CSingleton(){}
public:
	virtual ~CSingleton(){}
	static _ty* InitInstance(){
		if (m_pThiss) throw NULL;
		m_pThiss=new _ty;
		return m_pThiss;
	}
	static void DestoryInstance(){
		if (m_pThiss){
			delete m_pThiss;
			m_pThiss=NULL;
		}
	}
	static _ty* GetInstance(){
		if (!m_pThiss) throw NULL;
		return m_pThiss;
	}
private:
	static _ty* m_pThiss;
};

template<class _ty>
_ty* CSingleton<_ty>::m_pThiss=NULL;
#endif

观看上述代码,看看模板为我们解决了什么问题

1.解决了在基类中无法定义子类的静态指针成员的问题(因为子类都是未知的)

2.模板参数的不同,就代表不同的类,说明该模板类正好能为某一个子类提供一个唯一的基类,以及一个唯一的静态指针成员

3.由于不需要知道子类,所以该模板类不需要包含子类声明,而仅仅需要子类包含该模板类声明

 

上面三点,看不明白就算了,我感觉我都有点描述不清楚...但是又不想长篇累牍的去描述.就这样吧,反正这个不重要.

关于这个模板类的说明,我们可以看到模板类包含哪些东西:

1.一个指向类型参数_ty的静态成员指针,这个指针用于保存子类对象的索引

2.静态函数InitInstance,该函数用于初始化单实例类

3.静态函数DestoryInstance,该函数用于销毁单实例类

4.静态函数GetInstance,该函数用于获取单实例类指针

 

上述代码可以看到,InitInstance中如果m_pThiss不为空就直接throw null,而又没有去处理这个异常.这会让程序直接崩溃.这里再话痨一下,今天不知怎的,话多...

对于错误处理,我有一个概念是这样的:严己宽人.这里的己和人,分别指的是两种错误:

1.纯代码的错误,比如某些只能调用一次的函数,调用了两次.,这种错误,我称之主观错误

2.客观性错误,比如打开文件,或者访问网站的错误,这种错误是客观性的.无法通过修改代码来达到修正错误

对待主观性错误,我们应当立即抛出异常,让程序崩溃,而对待客观性错误,我们应当去做容错处理

当然,在敏捷开发中,或者说首次开发中,我们对待错误都应该直接抛出异常,让程序崩溃.在后面的修缮中,再来分辨主观错误和客观错误,然后对客观错误进行容错处理.

5.3 使用

#include "Fade/Singleton/Singleton.h"
#include "stdio.h"
class Test:public CSingleton<Test>
{
public:
	void ShowMsg(){
		printf("ShowMsg\r\n");
	}
};
int main()
{
	Test::InitInstance();
	Test* p=Test::GetInstance();
	p->ShowMsg();
	Test::DestoryInstance();
	return 0;
}

如上述代码所示:Test只需要派生于CSingleton<Test>,即可摇身一变成为一个单实例类.如此可方便的生成多个单实例类,而且负责实现单实例功能的代码<CSingleton>,Test中的逻辑代码不会有一丝一毫的耦合,其正交性绝佳.

多说一句:如果一个项目里面有多个数据需要使用单实例类,我希望的是根据逻辑划分创建多个单实例类.我见过有的项目,通过一个单实例类管理所有的数据的,那个类叫GlobalDataManager,那真的是十分的混乱.

5.4 小结

本小结介绍了一种实现单实例的方法,简单易用,且效果良好.从此可以摆脱通过Marco来实现单实例类的尴尬了.而且该模板类设计的非常具有技巧性,可以体现个人逼格,由于本人今天话比较多,写了很多无关紧要的语句,后面再回头来看的时候再看看那些需要精简吧


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值