全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1562
推到 Plurk!
推到 Facebook!

轉貼 : 偷龍轉鳳的物件設計方法

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-09-25 01:15:37 IP:61.70.xxx.xxx 未訂閱
此為轉貼文章 :   http://www25.brinkster.com/hltsai/Articles/LocalExtension.htm <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=big5"> <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> <meta name="ProgId" content="FrontPage.Editor.Document"> <title>偷龍轉鳳的物件設計方法</title> <style> <!-- pre { font-family: Courier New } --> </style> </head> <body Verdana">

偷龍轉鳳的物件設計方法

作者﹕陳國生
日期﹕Jun-7-2002

一般我們設計一個物件,規規矩矩的從VCL下選擇一個最符合本身需求的物計繼承下來,從這個物件開始擴充功能,但有時候這種標準的設計方式,有實際的困難,一者我們手上可能沒有這個物件的Source,二者更改這個物件之後,需考慮原先的物件可能已經在系統中運作,為了不破壞原有的物件功能,及使用的介面,這個時候我們需要一種偷龍轉鳳的方法,偷偷的把這個物件至換掉,要置換這個物件,最好的方法就是產生一個一模一樣的類別出來,而且不改變原有物件的屬性及方法,或者是在原有物件上擴充功能。
以下提供一個另類的設計方法,來解決這個問題。假如有一個TEdit 的物件,我們希望它在修改資料的時候,可以改變顏色,在不改變原有物件的使用介面下,如何來擴充這個功能呢﹖
請看這個範例的說明﹕
這個繼承自 TEdit 的 TMyEdit 很簡單的宣告 ReadOnly 這個屬性,其他 Create,Load 的方法,只是要在設計期間取得目前正確的顏色設定而已。
type 
  TMyEdit = class(TEdit) 
  private 
    FDesignColor: TColor; 
    FReadOnly: boolean; 
    procedure SetReadOnly(Value: boolean); 
    procedure SetColor; 
  protected 
    procedure Loaded; override; 
  public 
    constructor Create(AOwner: TComponent); override; 
  published 
    property ReadOnly: boolean read FReadOnly write SetReadOnly; 
end; 
接下來我們看 TMyEdit 如何改變原來的屬性,請把焦點放在 SetReadOnly上面,這個 procedrue 動了以下的手腳: 在繼承ReadOnly原有的屬性之後,進行顏色的改變。
procedure TMyEdit.SetReadOnly(Value: boolean); 
begin 
  FReadOnly:= Value; 
  inherited ReadOnly:= Value; 
  SetColor; 
end;
SetReadOnly 在父層類別 TCustomEdit 中已有定義,只是它被放在 private 區段裡,子類別是看不到的,否則只要改寫 SetReadOnly 方法就行了。在這裡重新定義了 ReadOnly 屬性,除了保有父類別 ReadOnly 屬性的作用,並賦予它新的行為。在設計類別時,也許將 Get/Set 存取方法宣告在 protected 區段會比較方便,後代類別可以直接改寫 Get/Set 方法來改變或附加行為,但這也表示父類別將失去對私有成員的保護力,子類別幾乎可以完全改變父類別的行為。因此,要把 Get/Set 放在 private 還是 protected 區段實為見仁見智的問題,設計者可視情況選擇對自己最有利的方式。 補充:蔡煥麟
以下是 TMyEdit 所有實作的部分﹕
constructor TMyEdit.Create(AOwner: TComponent); 
begin 
  inherited; 
  FDesignColor:= clWindow; 
end;     procedure TMyEdit.Loaded; 
begin 
  inherited; 
  FDesignColor:= Color; 
end;     procedure TMyEdit.SetColor; 
begin 
  if ReadOnly then 
    Color:= clBtnFace 
  else 
    Color:= FDesignColor; 
end;     procedure TMyEdit.SetReadOnly(Value: boolean); 
begin 
  FReadOnly:= Value; 
  inherited ReadOnly:= Value; 
  SetColor; 
end;
寫好這個物件我們開始進行測試,看這個物件如何無聲無息的嵌入我們已經寫好的單元,首先我們拉一個Form1出來,在上面放一個 Edit1 及 Button1,當然您還要建構這個 TMyEdit 的物件,為了方便起見,請將這個單元直接 Copy 到 Form1 所屬的單元裡頭,然後在 Button1 上面,寫入:
TMyEdit(Edit1).ReadOnly := False; 
執行看看,按一下 Button1,這時候 Edit1 的 ReadOnly 是不是多了改變顏色的功能﹖

結語

善用這個方法,可以讓原來的物件繼續工作,甚至還可以擴充新的方法出來,而不必更動原有的物件。你可以參考 Martin Fowler 的 Refactoring 書中關於 Introduce Local Extension 的說明。

讀者回應

陳先生 , 您好,小弟拜讀您在 dotspace 所寫的大作,心中有些疑惑,想跟您請教一下, 您於 "偷龍轉鳳的物件設計方法" 中所寫的 Sample ,您在 Button onClick 的事件中 ,雖然強迫將 Edit1 轉型使用 TMyEdit 的處理,但您又再 TMyEdit 的 SetReadOnly 的程序中,會使用到 FReadonly 這個 Field,這似乎會有問題吧,因為 Edit1 如果 是標準的 TEdit 的物件的話,那就不可能會有辦法去存取那個 Field ,個人覺得, 如果您的 Sample 程式改成如下的話,也許會比較合適.....,小弟才疏學淺,或許觀 念 有錯,因此想跟您請教一下,還望您能指點一下,Tks !!!! Regards, MCSE/OCP/SCJP 鼎新電腦 傅士哲
===========================================================================
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
Forms,
  Dialogs, StdCtrls;    type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}
type
  TMyEdit = class(TEdit)
  private
    function  GetReadOnly: boolean;
    procedure SetReadOnly(Value: boolean);
    procedure SetColor;
  published
    property ReadOnly: boolean read GetReadOnly write SetReadOnly;
  end;    function TMyEdit.GetReadOnly: boolean;
begin
  Result := inherited ReadOnly;
end;    procedure TMyEdit.SetColor;
begin
  if ReadOnly then
    Color:= clRed
  else
    Color:= clBlue;
end;    procedure TMyEdit.SetReadOnly(Value: boolean);
begin
  inherited ReadOnly := Value;
  SetColor;
end;    procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyEdit(Edit1).ReadOnly := not TMyEdit(Edit1).ReadOnly;
end;    end.
</body> </html> 發表人 - jackkcg 於 2002/09/25 01:29:16
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2002-09-26 22:15:44 IP:203.204.xxx.xxx 未訂閱
一般我們會想改變元件的某些能力,乃是因為我們喜歡或想要,而這代表幾乎每次使用到那個元件時都會想去改變,所以為何不直接將其設計成一個獨立的元件,這樣不用每次都要 Key 一堆東西,不用強迫程式做太多的 Typecast,而原來的元件也同時存在啊 !!
bruce
中階會員


發表:19
回覆:121
積分:83
註冊:2002-04-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-12-16 16:37:46 IP:211.21.xxx.xxx 未訂閱
synta 兄: 請仔細體會以下這段話: 一般我們設計一個物件,規規矩矩的從VCL下選擇一個最符合本身需求的物計繼承下來,從這個物件開始擴充功能,但有時候這種標準的設計方式,有實際的困難,一者我們手上可能沒有這個物件的Source,二者更改這個物件之後,需考慮原先的物件可能已經在系統中運作... 當初我寫這個範例,是從Refactoring 的觀念來的,這個觀念就是不要去改變現有的東西... 卻又產生可能的擴充空間,而不改變現有,卻是一個最困難的地方... 您覺得呢? 作者:陳國生
系統時間:2024-05-17 10:30:33
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!