進一步將界面代碼和功能代碼分離(基於DELPHI/VCL)之一
-----如何將界面代碼和功能代碼分離(基於Delphi/VCL)一文之補充建議
讀過Nicrosoft(奈軟) 朋友的‘如何將界面代碼和功能代碼分離’一個,
很是佩服, 仔細讀過之後, 我想補充我對在DELPHI上實現界面與功能代碼,這方面的體會。
還是拿Nicrosoft的個人通訊錄管理作為例子還說吧,
可參見:http://www.csdn.net/develop/article/8/8839.shtm
Nicrosoft朋友定義了一個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(哈欠)[email protected]
2000。7。15