两种Delphi实现Singleton模式方法

如何解决令人头痛的DCOM配置问题 有不少刚刚接触OPC通信的技术人员因为不熟悉DCOM配置倒在了OPC通信的“第一步”,那我们接下来就来看看如何完成令人头痛的DCOM配置。 阅读详情

两种Delphi实现Singleton模式方法

haozi


摘  要 本文描述了两种Singleton模式的Delphi实现方式,并做了对比分析。
关键字 设计模式,Singleton

Singleton(单件)模式是一种很有用的设计模式。它的意图的是:仅仅创建一个类的实例,并提供一个访问它的全局访问点。全局变量使的一个对象易被访问,但不能防止你实例化多个对象。单件模式的目的就是确保在程序的生命周期内只有一个实例存在。
看下面的代码:
procedure TForm1. Button1Click(Sender: TObject);
var  lS1 : TSingleton;  l
S2 : TSingleton;
begin
  try    lS1 := TSingleton.Create;   ////调用类的构造器   
    lS2 := TSingleton.Create;   ////调用类的构造器 
    //// ...别的代码 
  finally
    lS1.Free;  ////释放对象
    lS2.Free;  ////释放对象
  end;
end;

在上面的代码中第一次调用Create函数时TSingleton类被实例化,lS1指向一个内存存放对象的地址,当第二次调用TSingleton.Create函数时又重新实例化了TSingleton对象,lS2指向内存分配的另一个地址。Singleton模式就是让类自己负责保存他的唯一实例。

在上面的代码中就是让lS2创建的时候也指向lS1指向的对象(也就是被分配同一个内存地址),同样我们在释放lS1时必须防止内存被释放,因为单件对象还被lS2所引用。从而保证在程序的生命周期内有且只有一个类实例。
 《设计模式》C++的示例代码是使用C++的静态成员变量保存实例的,同时使用protected的构造器函数。但是在Delphi中由于没有静态成员变量,所以不能原样的使用该单件模式示例的方法。以下我们分析两种DELPHI实现Singleton模式的几种方法。

一.基于override两个Tobject虚拟函数的方法

class function NewInstance: TObject; virtual;
procedure FreeInstance; virtual;
NewInstance函数负责类对象创建的时候为对象分配内存,FreeInstance则相反释放内存


前者在对象构造时调用,后者在对象析构时调用。
我们使用两个全局变量来保存单件对象和对象的引用记数。
var  Instance  : TSingleton  = nil;
     RefCount : Integer     = 0;

TSingleton类的单元:
////---------------------------------------------------------------------------

////
unit uSingleton;

interface

type
  TSingleton = class(TObject)
  public
    class function NewInstance: TObject; override; ////覆盖基类函数
    procedure FreeInstance; override;              ////覆盖基类函数
    class function RefCount: Integer; ////返回当前引用记数
  end;

//// Declaration global variables
var
  Instance: TSingleton = nil;
  RefCount: Integer = 0;

implementation

{ TSingleton }

procedure TSingleton.FreeInstance;
begin
  Dec( RefCount );   ////减少引用记数
  if ( RefCount = 0 ) then  ////是否为0,是则释放内存
  begin
    Instance := nil;
//// 释放单件类的私有变量
////…
    inherited FreeInstance;
  end;
end;

class function TSingleton.NewInstance: TObject;
begin
  if ( not Assigned( Instance ) ) then
  begin
    Instance := TSingleton(inherited NewInstance);
    ////初始化私有变量 例子:
    ////   Instance.VariableName := Value;
  end;
  Result := Instance ;
  Inc( RefCount );
end;

class function TSingleton.RefCount: Integer;
begin
  Result := RefCount;
end;

end.
////---------------------------------------------------------------------------

////


当调用TSingleton的构造器的时候,会调用我们override的NewInstance函数,由NewInstance分配内存并返回给构造器,这样通过override的NewInstance函数我们确保了Create函数只可能实例化一个TSingleton对象(无论调用多少次Create只返回第一次分配的内存地址)。同时RefCount变量保存我们有几个到对象的引用。

我们在来看测试代码

procedure TForm1.Button1Click(Sender: TObject);
var
  lS1, lS2: TSingleton;
  Ob1, Ob2: Tobject;
begin
 lS1 := TSingleton.Create;
  ShowMessage(IntToStr(RefCount)); //// Ref_Count = 1
  lS2 := TSingleton.Create;
  ShowMessage(IntToStr(RefCount)); //// Ref_Count = 2
  Ob1 := TObject.Create;
  Ob2 := Tobject.Create;
  if lS1 = lS2 then
    ShowMessage('地址相等') //// lS1 = lS2
  else
    ShowMessage('地址不相等');
  if Ob1 = Ob2 then
    ShowMessage('地址相等')
  else
    ShowMessage('地址不相等'); //// Ob1 <> Ob2
end;
当程序调用析构器的时候(就是调用FREE函数的时候),析构器会调用FreeInstance函数释放被构造器分配的内存。Override的FreeInstance函数保证引用记数为零的时候才释放单件模式对象的内存。
下面是我们的测试代码:
var
  lS1 : TSingleton;
  lS2 : TSingleton;
begin
 try
    lS1 := TSingleton.Create;   ////调用类的构造器
    lS2 := TSingleton.Create;   ////调用类的构造器
  //// ...别的代码
  finally
    lS1.Free;  ////这里会首先调用我们覆盖定义的FreeInstance,
              ////由于这时RefCount在减1后为1,单件对象没有被释放
    lS2.Free;  ////dec(RefCount)= 0 释放单件对象
  end;
end;

上面这种单件模式实现方法很好地实现了由类自身来负责保存自己的唯一实例(通过截取创建新对象的请求——参考《设计模式》。它对TSingleton类的使用没有特殊的限制——程序员可以随意的调用Create和Free函数。
本模式的缺点是:该TSingleton类不能作为父类继承生成子类。如果继承生成两个子类,Create时只产生一个对象。
procedure TForm1.Button1Click(Sender: TObject);
var
  lS1 : 子类一;
  lS2: 子类二;
begin
  lS1 := 子类一.Create;
  lS2 := 子类二.Create;  ////不会创建子类二,lS2将指向lS1指向的内存,
                        ////也就是  lS1 = lS2end;

二.《设计模式》上示例的Delphi实现
 《设计模式》的实现示例是通过私有构造器函数来实现控制只产生一个对象实例。但该给出的C++代码实现未给出对象如何释放。Delphi里面不能实现Create函数的私有化,我们新定义一个函数来代替Create函数,同时屏蔽父类的Create函数。代码如下


////---------------------------------------------------------------------------

////
unit uSingletonUnit;

interface
uses
  Classes, SysUtils;
type

  TCSingleton = class(TComponent)  ////从Tcomponent类继承来。
  private
constructor CreateInstance(AOwner: TComponent); ////传递Owner参数
//// 这样TCSingleton类对象就会随Owner一起销毁(拥有者负责销毁TCSingleton对象)
  public
    constructor Create(AOwner: TComponent); override;
    class function Instance(AOwner: TComponent): TCSingleton;
  end;

var
  gCSingleton: TCSingleton;  //// Global variables

implementation

{ TCSingleton }

constructor TCSingleton.Create(AOwner: TComponent);
begin
////屏蔽Create函数的功能
  raise Exception.CreateFmt('Access class %s through Instance only',
    [ClassName]);
end;

constructor TCSingleton.CreateInstance(AOwner: TComponent);
begin
  ////新定义的构造函数Private型的
  inherited Create(AOwner);
end;

class function TCSingleton.Instance(AOwner: TComponent): TCSingleton;
begin
  if not Assigned(gCSingleton) then
    gCSingleton := TCSingleton.CreateInstance(AOwner);
  Result := gCSingleton;
end;

end.
////--------------------------------------------------------------------------/

/
上面的实现类使用过程中,程序员不用考虑单件模式对象的销毁问题。只是不能调用Create,必须调用Instance函数来获得对象的实例,同时把单件拥有者作为参数传递到函数里。这种实现方法可以作为基类被继承,用在状态模式的单件里(参见参考文献4),实现执行时的多态。
三.结束语

Singleton 模式的Delphi实现在网上还能查着其他的一些实现方式,本文的两种方法上

最常见的和简单的。同时其它方法的思路也很跟以上两方法很相似。

以上例子均没有考虑多线程的情况。
作者EMAIL:wuch@km169.net

参考文献:
1.《Creating a real singleton class in Delphi》 by Lasse
2.《Delphi 5 开发人员指南》机械工业出版社 2000.7
3.《设计模式》机械工业出版社 2000.9
4.《UML和模式应用》机械工业出版社 2002.1等

DCOM配置 要进行DCOM安全配置,操作者通常必须拥有客户和服务器计算机的管理员权限。   (1) 用户的建立及配置   最简单的用户配置是在客户和服务器计算机上建立名称、密码都相同的用户(Administrator权  限不是必需的),并用此用户登录系统、运行OPC服务器程序。这种方式适用于系统调试期间,或对安全  要求不高的场合。 在有一定安全要求的系统中,可按 阅读详情

相关推荐

实现电脑同时上内网和外网(或通过外网访问到该电脑通过该电脑访问内网)

一、需求描述 目前使用的公司网络只能够上内网,但是又有上外网查资料的需求: ①想要实现电脑既能上内网的同时也可以上外网; ②想要使用其他外网电脑使用外网连接到该电脑,通过该电脑访问内部的网络内容。 二、准备内容 电脑必须具备两个网卡,即:可以同时连接内网和外网(比如我的笔记本就可以:使用网线连接笔记本网口与内网通讯,使用WIFI连接手机热点访问外部网络); 注意:如果只有一个网口,可以另外购买USB的无线网卡来实现上网卡。 三、实现电脑同时上内网和外网的操作步骤 3.1、网络拓扑图 ..

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 2万+

Delphi设计模式之单例二

​接上篇Delphi设计模式之单例一,细心的朋友可能发现我在上一篇文章中重写类NewInstance和FreeInstance函数,原因是:【在delphi中编译器对构造函数的保护级别进行了处理,即便设为private,编译器仍然会将其修正为public,所以覆盖基类中的NewInstance类方法,系统在每次构造对象时都会调用这个类方法,通过重载它就可以实现对构造函数的控制】,同时在上篇文章中有一段核心代码 我以注释的形式标注这里在并发环境下存在安全隐患,那么现在我们就通过多线程的方式研究一下这个问.

舞动的代码 575

第3讲:单端传输线的时域TDR仿真(基于实战的第一次仿真视角切换)

本文为CST仿真系列教程的第3讲,主要介绍传输线阻抗(TDR)的两种仿真方法:基于S参数的频域计算和基于高斯脉冲的时域计算。文章详细演示了在CST PCB Studio中修改电容参数、设置TDR仿真参数(包括截止时间和采样点数)的操作步骤,并通过对比实验展示TVS寄生电容对阻抗曲线的影响。最后将两种TDR方法的结果进行对比,验证了两种方法的一致性。本教程适合硬件工程师通过时域波形直观分析传输线阻抗特性,是信号完整性分析的重要技能。

一只豌豆象的博客 171

Delphi中单例

//Delphi7以下均没有私有构造函数,当把构造函数写在Private中,在创建对象时,编译器会直接找到根类的Create来执行。所以一般都用NewInstance来实现单例。 NewInstance方法是在根类的Create中,只要在这个函数中判断实例是否存在,就OK了。

笑青天的专栏 1008

NewInstance与Create的区别

Create在执行的时候会先自动判断对象是否已分配内存,没有的话调用NewInstance来获取内存,然后再执行构造函数中的内容。NewInstance不会执行构造函数,只会分配对象内存。

YanJinrong的专栏 333

Delphi实现Singleton模式

Singleton模式定义:Singleton(一般译作单件或单态)模式,它是设计模式中比较简单而常用的模式。有些时候在整个应用程序中,会要求某个类有且只有一个实例,这个时候可以采用Singleton模式进行设计。 关于Singleton模式的详细介绍,请参见GOF的著作《设计模式》,俺比较节省纸张,不摘抄过来了。实现方法:在Delphi中有两个方法是负责创建与销毁对象的:clas

vchelp小鱼儿的Blog 1864

OPC DA的DCom配置

目录 一、OPCDA的Dcom配置文档 1.准备 1.1 OPC运行库 1.2 创建用户并赋予访问权限 :计算机管理 2.配置说明 2.1 防火墙关于 DCOM 和 OPC 的规则 :高级安全 Windows Defender 防火墙 2.2 配置 DCOM 安全:组件服务 2.3 配置本地安全策略 : 2.4.关于Matrikon的DCOM配置 3.用户 3.1 创建用户 3.2添加到DCOM组 4.防火墙 4.1 配置防火墙规则:开放 DCOM 访问 4.2 创建 O.

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 1万+

(详细)OPC DCOM配置

最近在研究OPC协议,需要利用COM或DCOM的方式成功连接到OPC服务器获取流量,。废话不多说,直接上才艺。(有什么疑问可以评论区留言,共同探讨,共同成长哈)下面是我使用的客户端软件连接:链接: https://pan.baidu.com/s/1tvA8LFYlVpn5II8eaqEzCA 提取码: 2gip ,自己也可到Matrikon OPC官网去下载。

weixin_46810015的博客 1万+

win10系统下的DCOM配置

OPC远程访问OPCServer的DCOM配置保证OPCServer和Client在局域网内OPC环境配置DCOM配置如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出...

weixin_43939712的博客 1万+

DELPHI的原子世界(转贴)

第1章  uo DELPHI的原子世界“天苍苍,野茫茫,风吹草低见牛羊”在使用DELPHI开发应用软件的过程中,我们就像草原上一群快乐牛羊,无忧无虑地享受着Object Pascal语言为我们带来的温暖阳光和各种VCL控件提供的丰富水草。抬头望望无边无际蔚蓝的天空,低头品尝大地上茂密的青草,谁会去想天有多高?地有多大?阳光和水草又是从何而来?那是大师关心的事。而大师此时正坐在高高的山顶上,仰望宇宙

Qi_jianzhou的资料室 1098

NewInstance 是分配内存

<br />NewInstance 是分配内存<br />create 对象的执行范围

diligentcat的专栏 792

19.Delphi自定义部件的开发

====================================================== 注:本文源代码点此下载 ====================================================== delphi除了支持使用可视化部件所见即所得地建立应用程序外,还支持为开发应用而设计自己的部件。 在本章中将阐述如何为delphi应用程序编写部

javazhuanzai的专栏 556

悟透delphi 第二章 DELPHI与WIN32时空

====================================================== 注:本文源代码点此下载 ====================================================== 本书原著李战(leadzen)大牛,由tingsking18整理,本人blog发布的版本经过战哥同意,转载请著名出处和原作者! 第二章delph

javazhuanzai的专栏 436

Delphi - 对象构造浅析后续

技术交流,DH讲解. 之前一篇文章已经讲过对象构造的过程,但是我们那个对象无任何东西,这里我们在已有的基础上面加点儿东西再来看看.代码改成: THuangJacky = class private FName:string; public procedure SayMyName(); constructor Create(); end; ...

weixin_34279061的博客 120

Delphi对象模型(Part IV) (转)

Delphi对象模型(Part IV) (转)[@more@] Delphi对象模型 (PART IV) XML:namespace prefix = o ns = "urn:schemas-microsoft-com:...

cuiji1279的博客 219

悟透delphi 第一章 delphi的原子世界

经过多方查找,总算基本找齐战哥的处女作《悟透delphi》的手稿。不敢独占,于是拿出来于大家共享。 第一章  DELPHI的原子世界第二章  DELPHI与WIN32时空第三章  多线程第四章  接口第五章  包第六章  事件与消息第七章  组织你的模块第八章  探索数据库第九章  多层体系结构第十章  操作界面与操作逻辑第十一章  面向对象数据库基础本书原著李战(leadzen)

我一路走来--- 8524

Delphi 实现单例模式Singleton Pattern)

原文:http://www.faceker.com/200808/delphi-singleton-pattern.html单例模式顾名思义就是一个实例,在任何情况下,系统中只能存在某一对象的一个实例。单例模式在应用开发中比较常见,如 Application 或 Logger。在 Delphi 的以前版本中,实现单例模式比较“另类”,自从 Delphi 后期加入一些新的语法元素后,单例模式

桂林哈秋 - 我想学编程 4283

[转]delphi中关于资源释放(Free/release/freeAndNil)的一点体会

[转]delphi中关于资源释放(Free/release/freeAndNil)的一点体会 经过这段时间对delphi中free 和 release 的仔细学习,先总结如下:1。form.free直接释放资源后,调用OnDestroy事件,但是没有将form指针改为nil2。form.release 等待资源不再使用后释放资源,同样不修改form指针为nil,所以在destroy中最好使用 

嵌入式系统,linux,存储 1595

ABS_MP_TS9_滑移率_ABS_

ABS防抱死设计,限滑设置 滑移率设置 最低车速限制

下一篇: 代码重构——之获得封装性DELPHI编码实例
haozi
博客等级 码龄26年 1粉丝 5原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值