站长资讯平台首页> 程序设计 > delphi >
[技术贴]关于动态代理
2008-04-09 04:21:39来源:互联网 阅读 ()现在,如果你是这个接口的用户,而这个接口及其实现者提供了一个: Foo : IFoo;
给你,其中Foo指向TFooImpl的一个实例。现在你有了IFoo的定义,和这个Foo实例--注意,你没有TFooImpl的定义和实现代码。如果现在要求你为所有的IFoo.doSth增加事务功能(假设doSth被实现为对数据库作更新操作),要怎么办?
GoF的Proxy模式就是解决方案之一:
如果所示,首先要实现一个新的IFoo接口实现--TStaticProxy。其中用了一个属性FImpl记录了TFooImpl的实例。然后在 TStaticProxy中实现doSth和bar,并且将不需要变更的bar函数直接委托给FImpl处理,而在doSth的实现里加入事务处理即可。 TStaticProxy的代码大致如下:TStaticProxy = class( TInterfacedObject, IIFoo )
private
FImpl : IFoo;
public
constructor Create( aImpl : IFoo );
function doSth( ... ) : xxx;
function bar( ... ) : xxx;
end;
constructor TStaticProxy.Create( aImpl : IFoo );
Begin
FImpl := aImpl;
End;
function TStaticProxy.doSth( ... ) : xxx;
Begin
BeginTransaction;
Result := FImpl.doSth( ... );
EndTransaction;
End;
function TStaticProxy.bar( ... ) : xxx;
Begin
Result := FImpl.bar( ... );
End;
然后,在所有需要用到Foo对象的地方,改用新的NewFoo对象,如下:var
NewFoo : IFoo;
Begin
NewFoo := TStaticProxy.Create( Foo ) As IFoo;
... // 之后就可以把NewFoo完全当作Foo一样使用了。
End;
可见,我们通过了一个Proxy类代理了所有对IFoo接口的操作,相当于在从IFoo到TFooImpl之间插入了自己的代码,在某种程度上,这就是AOP所谓的“横切”。当然如果你能有TFooImpl的代码的话,就简单了,只要如下:
从TFooImpl派生一个TNewFooImpl,然后在其中Override一下TFooImpl中的doSth即可,然后就创建TNewFooImpl的实例来代替Foo引用即可。
但问题就在于你必须拥用TFooImpl的代码,并且可以变更所提供的Foo实例,但这在很多时候是做不到的--除非不是用DELPHI,而是如 Python一类的动态语言^O^。比如组件容器,比如远程实例等。还有像“虚代理”(就是当创建FImpl代价很高时,就在创建时只创建代理类,然后在真正需要时才创建FImpl的实例)
但上面这种静态代理还是很麻烦。首先,如果IFoo的成员函数很多的话,必须要一一为它们加上代理实现;其次,如果在应用中有很多接口需要代理时,就必须一一为它们写这样的专用代理类;第三,需要变更代理功能时,需要修改所有的代理类……
特别是像组件容器或是通用远程代理这样,对要实现的接口并不能确定的情况下,静态代理一点用也没有。
所以我们需要“动态代理”。我是在看了GIGIX发表在今年第一期《程序员》上的《动态代理的前世今生》一文后,虽然他说是的JAVA在 JDK1.3中提出的,在java.lang.reflect中的proxy。但这却让我突发奇想,发现其实完全可以在DELPHI里也实现这样一个动态代理。
一个典型的动态代理如下:
这样,我们只需要把要增加在功能做成一个IInvocationHandler接口的实例,如图中的TFooInvHandler。然后动态创建一个支持IFoo接口的TDynamicProxy的实例--它是一个动态代理,只需要传入相应的参数:要实现的接口和相应的InvHandler实例即可,不需要为每个接口写一个代理。当然如GIGIX文中所说,对于C 来说,这个可以用模板实现,但问题在于模板归根到底是一种编译时的动态化技术,对于组件容器这样需要运行时动态化的应用,它还是不能实现。最后,InvHandler通过RTTI去调用具体的实现Foo。
它的用法大致如下:TFooInvHandler = class( TInterfacedObject, IInvocationHandler )
private
FImpl : IFoo;
public
constructor Create( aImpl : IFoo );
function Invoke( IID, MethodName, Args[] ) : xxx;
end;
constructor TFooInvHandler.Create( aImpl : IFoo );
Begin
FImpl := aImpl;
End;
function TFooInvHandler.Invoke( IID, MethodName, Args[] ) : xxx
Begin
If ( IID = IFoo ) AND ( MethodName = ''''doSth'''' ) Then
Begin
BeginTransaction;
Result := DoInvoke( FImpl, IID, MethodName, Args[] );
EndTransaction;
End
Else
Result := DoInvoke( FImpl, IID, MethodName, Args[] );
End;
var
Handler : IInvocationHandler;
NewFoo : IFoo;
Begin
Handler := TFooInvHandler.Create( Foo );
NewFoo := TDynamicProxy.Create( TypeInfo(IFoo), Handler ) As IFoo;
... // 之后就可以把NewFoo完全当作Foo一样使用了。
End;
注意:其中IInvocationHandler接口我还没想好要怎么定义,所以这段代码只是大致说明一下问题。另外,其中的DoInvoke就是通过RTTI来调用FImpl的。
从上面的代码可以看到,TDynamicProxy通过参数IFoo动态生成了一个对IFoo接口的代理,并且通过Handler参数插入一个处理接口IInvocationHandler,由TDynamicProxy把对IFoo接口的调用全部转成对IInvocationHandler接口的调用,最后由TFooInvHandler类来视情况处理。在这里,可以通过运行时配置方式来动态决定是否需要切入事务所处理,需要对哪个接口的哪个方法切入。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有网页中Delphi代码语法上色程序 源代码Delphi中的布尔类型主机资讯注册资讯托管资讯vps资讯网站建设建站经验策划盈利搜索优化网站推广免费资源联盟新闻联盟介绍联盟点评网赚技巧搜索引擎网络游戏电子商务广告传媒Asp.Net编程Asp编程Php编程Xml编程AccessMssqlMysql其它Web服务器Ftp服务器Mail服务器Dns服务器安全防护其它软件WordExcelPowerpointGhostVistaQQ空间QQFlashGet迅雷FrontPagesDreamweaverJavascriptcssphotoshopfireworksFlashJava技术C/C++VBdelphi网络协议网络安全网络管理组网方案Cisco技术Win2000WinXPWin2003Mac OSLinuxFreeBSDjava系统c程序设计计算机二级javajava自学教程java微信开发入门视频教程c语言图形界面编程java技术论坛java 框架java教学java并发编程实践java开发工具有哪些delphi视频教程javafx教程java框架有哪些java下载安装教程java可以做什么delphi法java基础视频Photoshop绘制立体风格的微笑表情PS文字特效教程:制作公路上个性的涂鸦Photoshop设计卷边效果的变形金刚电影PS色彩修复教程:利用色阶工具快速给红PS半透明物体抠图:利用通道选区工具抠PS海报设计技巧教程:学习制作个性的扭PS图片特效制作教程:学习给铁塔图片制学习用photoshop把浑浊的海水照片后期PS古风照片教程:给古风美女打造出女侠PS个性人物海报制作:设计创意时尚的玻WebAPI搭建(二) 让WebAPI 返回JSON格人民币小写转换为大写的演示程序制作QQ消息炸弹设置打印机后台打印数据格式的几个办法龙岩市商品房备案登记查询系统 (INTRAWVS中生成网站和发布网站的区别Delphi 函数参考uniGUI学习汇总一些老控件的集合下载包uCommand v1.1 (通用命令调用机制)谷歌移动友好算法AVPSFTP软件IEloadimg使用POSTHTTPCOMHTMLem定义数据timwordClass网络安全运维经验IT技术分享运维随笔录鲜花东郊到家往约到家
智能索引记录
-
2026-04-10 07:41:16
新闻资讯
成功
标题:《白日提灯》花絮释出 拍摄花絮 迪丽热巴 拍摄现场 娱乐资讯 迪丽热巴·迪力木拉提 幕后花絮_网易视频
简介:《白日提灯》花絮释出
-
2026-04-24 00:53:16
综合导航
成功
标题:The Lighter Side Montréal Canadiens
简介:Kick back and enjoy the laughs with an inside look at the Ca
-
2026-04-22 13:26:00
综合导航
成功
标题:CZ has built a position in ASTER. Will this shake Hyperliquid’s position? Bee Network
简介:On the evening of November 2, Zhao Changpeng announced that
-
2026-04-13 11:12:29
电商商城
成功
标题:ainol艾诺怎么样 - 京东
简介:京东是专业的ainol艾诺网上购物商城,为您提供ainol艾诺价格图片信息、ainol艾诺怎么样的用户评论、ainol艾
-
2026-04-16 17:32:51
教育培训
成功
标题:户口本改名字的程序详解-起点起名网
简介:易名轩起名网整理了“户口本改名字的程序详解”相关的文章,起点起名网是免费起名学习交流平台,以音形义、流行趋势、心理学暗示