设计模式C++实现(2)——单例模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》(DP)两本书。本文介绍单例模式的实现。

      单例的一般实现比较简单,下面是代码和UML图。由于构造函数是私有的,因此无法通过构造函数实例化,唯一的方法就是通过调用静态函数GetInstance。

      UML图:

      代码:

[cpp] view plaincopyprint?
  1. //Singleton.h  
  2. class Singleton    
  3. {  
  4. public:  
  5.     static Singleton* GetInstance();  
  6. private:  
  7.     Singleton() {}  
  8.     static Singleton *singleton;  
  9. };  
  10. //Singleton.cpp  
  11. Singleton* Singleton::singleton = NULL;  
  12. Singleton* Singleton::GetInstance()  
  13. {  
  14.     if(singleton == NULL)  
  15.         singleton = new Singleton();  
  16.     return singleton;  
  17. }  

       这里只有一个类,如何实现Singleton类的子类呢?也就说Singleton有很多子类,在一种应用中,只选择其中的一个。最容易就是在GetInstance函数中做判断,比如可以传递一个字符串,根据字符串的内容创建相应的子类实例。这也是DP书上的一种解法,书上给的代码不全。这里重新实现了一下,发现不是想象中的那么简单,最后实现的版本看上去很怪异。在VS2008下测试通过。

[cpp] view plaincopyprint?
  1. //Singleton.h  
  2. #pragma once  
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. class Singleton    
  7. {  
  8. public:  
  9.     static Singleton* GetInstance(const char* name);  
  10.     virtual void Show() {}  
  11. protected//必须为保护,如果是私有属性,子类无法访问父类的构造函数  
  12.     Singleton() {}  
  13. private:  
  14.     static Singleton *singleton; //唯一实例的指针  
  15. };  
  16.   
  17. //Singleton.cpp  
  18. #include "Singleton.h"  
  19. #include "SingletonA.h"  
  20. #include "SingletonB.h"  
  21. Singleton* Singleton::singleton = NULL;  
  22. Singleton* Singleton::GetInstance(const char* name)  
  23. {  
  24.     if(singleton == NULL)  
  25.     {  
  26.         if(strcmp(name, "SingletonA") == 0)  
  27.             singleton = new SingletonA();  
  28.         else if(strcmp(name,"SingletonB") == 0)  
  29.             singleton = new SingletonB();  
  30.         else   
  31.             singleton = new Singleton();  
  32.     }  
  33.     return singleton;  
  34. }  
[cpp] view plaincopyprint?
  1. //SingletonA.h  
  2. #pragma once  
  3. #include "Singleton.h"  
  4. class SingletonA: public Singleton  
  5. {  
  6.     friend class Singleton; //必须为友元类,否则父类无法访问子类的构造函数  
  7. public:  
  8.     void Show() { cout<<"SingletonA"<<endl; }  
  9. private:   //为保护属性,这样外界无法通过构造函数进行实例化  
  10.     SingletonA() {}   
  11. };  
  12. //SingletonB.h  
  13. #pragma once  
  14. #include "Singleton.h"  
  15. class SingletonB: public Singleton  
  16. {  
  17.     friend class Singleton; //必须为友元类,否则父类无法访问子类的构造函数  
  18. public:  
  19.     void Show(){ cout<<"SingletonB"<<endl; }  
  20. private:  //为保护属性,这样外界无法通过构造函数进行实例化  
  21.     SingletonB() {}  
  22. };  
[cpp] view plaincopyprint?
  1. #include "Singleton.h"  
  2. int main()  
  3. {  
  4.     Singleton *st = Singleton::GetInstance("SingletonA");  
  5.     st->Show();  
  6.     return 0;  
  7. }  

       上面代码有一个地方很诡异,父类为子类的友元,如果不是友元,函数GetInstance会报错,意思就是无法调用SingletonA和SIngletonB的构造函数。父类中调用子类的构造函数,我还是第一次碰到。当然了把SingletonA和SIngletonB的属性设为public,GetInstance函数就不会报错了,但是这样外界就可以定义这些类的对象,违反了单例模式。
       看似奇怪,其实也容易解释。在父类中构建子类的对象,相当于是外界调用子类的构造函数,因此当子类构造函数的属性为私有或保护时,父类无法访问。为共有时,外界就可以访问子类的构造函数了,此时父类当然也能访问了。只不过为了保证单例模式,所以子类的构造函数不能为共有,但是又希望在父类中构造子类的对象,即需要调用子类的构造函数,这里没有办法才出此下策:将父类声明为子类的友元类。

      本人享有博客文章的版权,转载请标明出处 http://blog.csdn.net/wuzhekai1985

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436143.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式C++实现(3)——建造者模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性&#xff1a;封装、继承、多态&#xff0c;真正领悟设计模式的精髓是可能一个漫长的过程&#xff0c;需要大量实践经验的积累。最近看设计模式的书&#xff0…

宽字符串忽略大小写比较的实现(原)

宽字符串忽略大小写比较的实现(原) 孙文涛 2008-07-24 在Mac机器平台上没有wcsicmp 或 wcscasecmp之类的函数实现对宽字符忽略大小写的比较&#xff0c;所以实现了好几种方法。 一个自然的思路是: (1) wcscpy 原字符串到tmp字符串; (2) tolower tmp字符串; (3) 然后调用仅存的w…

有关JAVA考试中数据库的题,javaee期末考试题库,用javaEE编写一个题库系统,要怎么做...

javaEE数据库简单问题。你插入2113数据库的时候是把5261它封装为一4102个对象插入的吗&#xff1f;1653如果封装为一个User对象版的权话(User对象有ID和LEVEL两个属性)ResultSet rs ps.executeQuery();User user new User();if(rs.hasNext()){user rs.next();}关于javaee 中j…

oracle 12c sql图形化,Oracle 12c PL/SQL程序设计终极指南

Oracle 12c PL/SQL程序设计终极指南作者&#xff1a;孙风栋;王澜;郭晓惠出版日期&#xff1a;2015年06月文件大小&#xff1a;11.73M支持设备&#xff1a;&#xffe5;60.00在线试读适用客户端&#xff1a;言商书局iPad/iPhone客户端&#xff1a;下载 Android客户端&#xff1a…

oracle 存储同步,Oracle数据库知识——存储过程篇

在线QQ客服&#xff1a;1922638专业的SQL Server、MySQL数据库同步软件存储过程是一组用于完成特定功能的SQL语句&#xff0c;该语句已编译并存储在数据库中。用户通过指定存储过程的名称并提供参数(如果存储过程具有参数)来执行它。存储过程是数据库中的重要对象。任何设计良好…

使用MvcContrib的FormHelper

MvcContrib的FormHelper提供了三大Helper Html辅助 验证HelperGrid表格Helper下载 下载后将MvcContrib.dll与MvcContrib.Samples.FormHelper.dll引用到Asp.net MVC工程 在Web.Config pages.namespaces加入以下节点 <add namespace"MvcContrib.UI.Tags"/><ad…

WinCE控制面板添加应用程序

WinCE系统中的控制面板和Windows系统中的控制面板原理是一样的&#xff0c;里面就是包含了一些应用程序。WinCE系统的控制面板由Ctlpnl.exe&#xff0c;Control.exe和一些.cpl文件组成&#xff0c;其中Ctlpnl.exe和Control.exe用于控制控制面板的文件夹显示和架构&#xff0c;而…

oracle 游标 904,如何解决Oracle数据库游标连接超出问题

如何解决Oracle数据库游标连接超出问题发布时间&#xff1a;2020-07-21 10:57:35来源&#xff1a;亿速云阅读&#xff1a;103作者&#xff1a;小猪这篇文章主要讲解了如何解决Oracle数据库游标连接超出问题&#xff0c;内容清晰明了&#xff0c;对此有兴趣的小伙伴可以学习一下…

用多媒体库 Bass.dll 播放 mp3 [15] - 设置与获取播放速度

本例效果图:代码文件:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ComCtrls;typeTForm1 class(TForm)OpenDialog1: TOpenDialog;Button1: TButton;Button2: TButton;Button3: TButton;TrackBar1:…

【转】Dicom文件解析!!!!!!

转自&#xff1a;https://blog.csdn.net/leaf6094189/article/details/8510325 Dicom全称是医学数字图像与通讯&#xff0c;这里讲的暂不涉及通讯那方面的问题 只讲*.dcm 也就是diocm格式文件的读取&#xff0c;读取本身是没啥难度的 无非就是字节码数据流处理。只不过确实比较…

VS2008 JS脚本调试总是调试旧代码 真不知道怎么回事?谁能帮帮我呀!

如图,[dynamic]标记的是调试的元文件 xml1.htm[dynamic]和xml.js[dynamic] 我更改后的文件是xml1.htm和xml.js,见图1 2 调试的文件有debugger 更改后的文件我把debugger注了 js脚本中我把变量给改了见3 4 ,所以在浏览新的xml1.htm时,竟然报对象找不到,真实受不了了!!! 为什么我…

【转】C#开发PACS医学影像处理系统(一):开发背景和功能预览

转自&#xff1a;https://www.cnblogs.com/Uncle-Joker/p/13646949.html 本系列文章将从以下模块和大家分享和讨论使用C#开发医学软件PACS和RIS系统&#xff0c; 国内相关资料比较少&#xff0c;也借此机会丰富一下医学软件开发生态&#xff0c;讨论技术难点&#xff0c;希望…

《WF编程》系列之30 - 基本活动:错误处理

《WF编程》系列之30 - 基本活动:错误处理 4.3 错误处理 Fault,故障,现在官方已经将其翻译为错误,那么以后的随笔中我也就采用官方的翻译吧. 错误处理也属于流程控制的一部分,这一节我来介绍一下有关错误处理的活动.错误是指在工作流执行期间发生的异常.我们可以使用错误处理程…

oracle错误27101,ORA-27101ORA-01034错误解决

Oracle已经启动&#xff0c;连接sqlplus后&#xff0c;进行查询&#xff0c;出现下面错误ORA-01034: ORACLE not availableORA-27101: shared memory realm doesOracle已经启动&#xff0c;连接sqlplus后&#xff0c;进行查询&#xff0c;出现下面错误ORA-01034: ORACLE not av…

NOD32升级ID获取器For流星无语更新了

NOD32升级ID获取器For流星无语更新了一下,现在可以直接把用户名密码写入注册表了,连复制/粘贴操作都可以免了...转载于:https://www.cnblogs.com/lxwy/archive/2008/09/05/4420722.html

【转】【C#】使用fo-dicom完成BMP,JPG,PNG图片转换为DICOM文件

转自&#xff1a;https://developer.aliyun.com/article/672065 最近研究了一下DICOM和BMP文件转换的问题&#xff0c;也是很头大。度娘了很久&#xff0c;也在CSDN等论坛看到一些断断续续的文件&#xff0c;最主要的是代码只是片断&#xff0c;不是完整的实现。头大了。 首先…

C++设计模式之二 AbstractFactory模式

设计模式的目的就是尽量减少“变化”对程序的影响&#xff0c;尤其是对客户程序的影响。AbstractFactory模式作为创建型模式的一种&#xff0c;解决的就是“new”在变化中可能引起的问题。 先来看看new有何种不好&#xff0c;举个创建汽车的车门的例子&#xff1a; 很自然的一…

改写DataCogs在MOSS列表中实现三级联动字段

项目中有需求需要实现列表中3级的字段联动。参照小熊的[分享]修复DataCogs二级联动FieldControl支持中文 &#xff0c;改造一下&#xff0c;实现了3级联动字段。另外&#xff0c;还可以实现一个列表中同时有两个&#xff0c;或两个以上互相独立的联动字段&#xff0c; 详细的字…

【转】01.Dicom 学习笔记-DICOM C-Store 消息服务

转自&#xff1a;https://www.jianshu.com/p/bab6a85d3486 引言 之前总体介绍了 DICOM 的消息服务&#xff0c;可以参考这篇博文&#xff0c;但是有关每个服务的详细信息没有讲解&#xff0c;本文就结合开源 DICOM 库 fo-dicom 详细介绍一下 C-Store 服务。 名词简介 在正式讲…

【转】02.Dicom 学习笔记-DICOM C-Find 消息服务

引言 前篇介绍了 DICOM C-Store 消息服务&#xff0c;本文结合开源 DICOM 库 fo-dicom 详细介绍一下 C-Find 服务。 C-Find 消息服务 C-Find 服务是一个查询服务&#xff0c;用于一个 DIMSE-service-user 在同等的DIMSE-service-user 上查询复合 SOP 实例的属性满足查询条件给出…