也谈将界面代码和功能代码分离(基于DELPHI/VCL)之一
进一步将界面代码和功能代码分离(基于DELPHI/VCL)之一
-----如何将界面代码和功能代码分离(基于Delphi/VCL)一文之补充建议
读过Nicrosoft(奈软) 朋友的‘如何将界面代码和功能代码分离’一个,
很是佩服, 仔细读过之后, 我想补充我对在DELPHI上实现界面与功能代码,这方面的体会。还是拿Nicrosoft的个人通讯录管理作为例子还说吧,
可参见:http://www.csdn.net/develop/article/8/8839.shtmNicrosoft朋友定义了一个TAddrBook的类来封装了一个地址簿存取操作的逻辑,
对外提供了
FindRecord, AddRecord, DelRecord。。。
等等必需的公共接口,
然后在一个TFORM作为地址簿的显示界面,仅使用这些公共接口去访问TAddrBook实例。
不涉及任何存取逻辑,每个模块的代码简单,易懂,便于维护。Nicrosoft的TAddrBook类是没有指定父类, 也就是说继承自TObject,因为我们
谈的DELPHI, 为了充分利用它的可视化环境(当然,不仅仅因为这点),
我建议将其继承于TDataModule, 简单地说,创建一个数据模块,将其命名为TAddrBook.仔细想想, 可能会发现仅仅这样,还有些地方不尽如人意,
在这个地址簿系统运行时,产生了一个TForm1类实例(暂称其Form1)
和一个TAddrBook类实例(暂称其AddrBook),它们之间通讯
是单向的,也就是说Form1知道AddrBook,而AddrBook不知道Form1,
Form1必需知道AddrBook是显而易见的,而AddrBook需要知道Form1吗?
这个嘛。。。。有点不大好说。。。至少有一个地方可能会需要的吧,
就是AddrBook记录改变的时候,得叫Form一声“喂,FORM,我变了”,
不过仅仅这样看来,它还是似乎可有可无,Form1可以主动去查询AddrBook的状态。再多想想, 如果另建了一个实例TForm2类呢? 或者是一个TForm1的多个类实例呢?
这样有两个以上的FORM都要去显示AddrBook,那情况会是怎么样?
说得实际些,比如说FORM1是个LISTVIEW显示,
而FORM2是个DETAIL显示与编辑, 在FORM1中选了另一个人,FORM2显然必须得相应的
变化,直接由FORM1通知FORM2吗? 这不是个好主意。
如果这样,独立自在的FORM,本来只需要知道AddrBook,还得知道其它的FORM,FORM的数量越多,
越有扯不清的关系。增加删除一个FORM还得看其它的FORM的脸色行事,NO,这样不爽!
那好吧, 就决定让AddrBook知道有哪些FORM在用它吧,然后在必要的时候通知大家自己状态变了,
再来读自己一次。
具体实现的方法很多, 我是比较喜欢用TList,
首先,TAddrBook的私有成员中加一个
private
FViewerList:TList;//用来保存使用TAddrBookr的FORM
...
然后,加上这几个方法。。
public
...
procedure AddViewer(form:TForm); //用AddrBook的FORM登个记
procedure RemoveViewer(form:TForm); //注销这个FORM的登记
procedure TellAllViewer(); //通知所有登记过的FORM...
procedure TAddrBook.AddViewer(form: TForm);
begin
FViewerList.Add(form);
end;
procedure Tfrm_Navigate.RemoveViewer(form: TForm);
begin
FViewerList.Remove(form);
end;
下面是通知所有使用TAddrBook的FORM, 有很多种方法的,
我这儿采用的是发送消息的方法,
已经自定义了一个消息
。。。
MY_ADDRBOOK_MSG =WM_USER+100;
。。。procedure TAddrBook.TellAllViewer;//告诉所有的FORM‘喂,都该起来做事了’
var
i:integer;
begin
for i := 0 to FViewerList.Count-1 do
begin
postMessage(
TForm( FViewerList.Items[i] ).Handle,
MY_ADDRBOOK_MSG,
0 , //这儿两个参数可以用来区分你发出通知的种类,
0 //不主张用它们来直接传数据回FORM,
//而是在通知让FORM来取数据
);end;
end;而在TFORM1中,加入消息处理方法。
TForm1 = class(TForm)
...
public
procedure AddrBookNotify(var Message: TMessage); message MY_ADDRBOOK_MSG;
...procedure TForm1.AddrBookNotify(var Message: TMessage);
begin
//在这里面重新读出AddrBook的信息,
//当然, 视你消息的分类,还可以处理得更细一些end;
AddrBook中的方法进行改变数据状态的行为后,需要FORM相应改变显示或其它类似的操作时,
就调用TellAllViewer方法。
罗里罗嗦,终于说得差不多了, 真累,
如果知道设计模式的朋友, 一眼就可以知道这是观察者模式, 也就是VC应用程序框架中
所采用的Doc /View 模式, 就一两句话可以搞定。之所以在标题上加了一个‘之一’, 是因为还有很多值得进一步思考的东西,
如果有必要, 我,或者其它有兴趣的朋友, 可以继续探讨,加上之二,之三。halfdream(哈欠)halfdream@sina.com
2000。7。15
补充:软件开发 , Delphi ,