亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

代碼重構——之獲得封裝性DELPHI編碼實例

2019-11-18 18:32:28
字體:
來源:轉載
供稿:網友
代碼重構——之獲得封裝性DELPHI編碼實例
 
代碼重構是獲得結構良好的方法,通過重構,我們在保持功能不變的情況下,改善代碼的質量,提高代碼的復用程度。下面是一個獲得改善代碼質量和獲得封裝性的一個具體的例子。(例子使用DELPHI)
代碼功能:
       給數據集設(TClientDataSet)置過濾器,用戶可以在一個TComboBox中選擇要過濾的字段,然后在一個Tedit框中輸入要過濾的值。如圖一:
最常見的做法就是在TComboBox的Items屬性中硬碼寫入我們數據集中的字段名稱,然后在代碼中加入一大堆case或者if語句在判斷用戶選擇的字段來給數據集設置過濾器。
……
      case ComboBox1.ItemIndex of
0:
             ClientDataSet.Filtered := False;
        ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + '''';
              ClientDataSet.Filtered := True;
1:
             ClientDataSet.Filtered := False;
        ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + '''';
              ClientDataSet.Filtered := True;
……       
end;                
或者用
….…
       if ComboBox1.Text = '物料編碼' then
    begin
              ClientDataSet.Filtered := False;
        ClientDataSet.Filter := ' F_CODE = ''' + Edit2.Text + '''';
              ClientDataSet.Filtered := True;
end
else if ComboBox1.Text = '名稱' then
begin
ClientDataSet.Filtered := False;
        ClientDataSet.Filter := ' F_CHINESE_NAME = ''' + Edit2.Text + '''';
              ClientDataSet.Filtered := True;
 
end
……
這樣的代碼通過硬碼同樣也實現了這個給數據集設置過濾器的功能,滿足了需求,但是上面這段代碼是不靈活的。如果數據集的字段很多就要求編碼人員一個一個字段錄入在Items中,而且在寫case必須核對好順序,不然設置的過濾器就是錯誤的也就很容易由開發人員引入BUG。用if語句時也一樣維護一個大量的if同樣是痛苦的,而且不支持需求變化,當用戶要求改變數據集字段的中文顯示名稱時必須也要記住更改TComboBox. Items中的硬碼數據,如果一旦忘記就會引入BUG。
 
于是我在第一次重構中,嘗試動態的加載TComboBox. Items中的數據,同時為了實現加載后用戶選擇時實現對照。我在這個查詢FORM中加了一個 私有FFields: array[0..20, 0..2] of string; 字段來保存數據集中的字段信息數據。同時實現了一個加載數據的過程:
 
PRocedure TFrmSPARealStorageQuery.GetQueryFields;
var
  i, iFieldsCount: Integer;
begin
  iFieldsCount := 0;
  with DBGride1.DataSource.DataSet do
  begin
    for i := 0 to Fields.Count - 1 do
      if Fields[i].Visible then
      begin
        FFields[iFieldsCount, 0] := Fields[i].FieldName;
        FFields[iFieldsCount, 1] := Fields[i].DisplayLabel;
        Inc(iFieldsCount);
      end;
    ComboBox1.Items.Clear;
    for i := 0 to iFieldsCount - 1 do
      ComboBox1.Items.Add(FFields[i, 1]);
  end;
end;
 
這樣就實現了在運行時動態加載字段信息。這樣我的過濾器設置就變成了這樣的。
 
if ComboBox1.Text <> '' then
begin
ClientDataSet.Filtered := False;
    ClientDataSet.Filter := FFields[ComboBox1.ItemIndex, 0] +  '''' + Edit2.Text + '''';
       ClientDataSet.Filtered := True;
end;
 
本方法無疑增加了代碼的靈活性,同時增加了代碼的復用度,因為代碼很好的隔離了變化的數據。因此只要在另一個也是要實現這種的功能的FORM中增加私有字段FFields: array[0..20, 0..2] of string 和使用上面的動態加載數據集字段過程,就可以說方便的實現了重用。但是這種重用并不是很好的,因為我們沒有實現很好的封裝性。導致在你的程序中到處散落有重復的代碼(你常常會通過COPY來獲得這個函數的重用,因為上面的代碼是沒有好的封裝性)。如果有一天你要修改數據裝載函數你就必須到處去找那里拷貝了該函數——你也得修改散落在其他地方的代碼。于是我進行了再一次的重構,并對代碼進行了進一步的封裝。
代碼如下:
unit uDataSetFieldsInfo;
// Description:單元包括 TDataSetFieldsInfo 類,該類封裝了獲得數據集子段信息。
// 并提供了在combobox列表顯示字段顯示信息和獲得對應子段名稱的方法接口
// Created : wuchhao
// Date : 2003.5
 
interface
uses Classes, DBClient, StdCtrls;
type
  TDataSetFieldsInfo = class
  private
    FFieldsList: TStrings;
  public
    constructor Create;
    destructor Destroy; override;
    procedure GetDataSetFields(Source: TClientDataSet);
    procedure ShowFieldsInfo(Target: TComboBox);
    function GetFieldsNameByDisplayLabel(DisplayLabel: string): string;
  end;
 
implementation
 
{ TDataSetFieldsInfo }
constructor TDataSetFieldsInfo.Create;
begin
  FFieldsList := TStringList.Create;
end;
 
destructor TDataSetFieldsInfo.Destroy;
begin
  FFieldsList.Free;
  inherited;
end;
 
procedure TDataSetFieldsInfo.GetDataSetFields(Source: TClientDataSet);
var
  i: Integer;
begin
  FFieldsList.Clear;
  with Source do
  begin
    for i := 0 to Fields.Count - 1 do
      if Fields[i].Visible then
      begin
        FFieldsList.Add(Fields[i].DisplayLabel);
        FFieldsList.Add(Fields[i].FieldName);
      end;
  end;
end;
 
function TDataSetFieldsInfo.GetFieldsNameByDisplayLabel(
  DisplayLabel: string): string;
var
  index: Integer;
begin
  Result := '';
  index := FFieldsList.IndexOf(DisplayLabel);
  if index <> -1 then
    Result := FFieldsList.Strings[index+1]  ;
end;
 
procedure TDataSetFieldsInfo.ShowFieldsInfo(Target: TComboBox);
var
  i: Integer;
begin
  Target.Items.Clear;
  i:=0;
  while i <  FFieldsList.Count do
  begin
    Target.Items.Add(FFieldsList.Strings[i]);
    i:= i+ 2;
  end;
end;
end.
 
單元uDataSetFieldsInfo 封裝了與實現本文所述功能相關的數據和方法,把它們封裝在一個類里面,從而實現了面向對象設計里面的 Open - Close 原則。類變成了一個黑盒,于是就可方便的重用(black-box reuse),而不必擔心代碼的重復。同時因為封裝了與功能相關的信息,類的職責定義明確(單職責),并有了足夠合適的粒度和好的封裝性。TdataSetFieldsInfo 很好的把組合框與變化的數據隔離開來,最終提高了代碼的復用程度,同時減少了FORM類的職責和 magic number硬編碼的量。下面是新的代碼:
首先在FORM中聲明TdataSetFieldsInfo類的一個引用。
……
在FORM創建的時候調用:
FFieldsInfo := TDataSetFieldsInfo.Create;
FFieldsInfo.GetDataSetFields(cdMaster);
FFieldsInfo.ShowFieldsInfo(ComboBox1);
這時候我的過濾器設置就變成了:
if ComboBox1.Text <> '' then
begin
ClientDataSet.Filtered := False;
    ClientDataSet.Filter := FFieldsInfo.GetFieldsNameByDisplayLabel(ComboBox1.Text) +  '''' + Edit2.Text + '''';
       ClientDataSet.Filtered := True;
end;
 
通過調用FfieldsInfo對象的接口過程來獲得對應的子段名稱。
 
本文是一個重構代碼的簡單例子,我想上面我實現的這個類還可以有很多種寫法和更好的算法。這里只是提供一種關于重構代碼的思路,為提高我們的編寫代碼質量和它的可維護性、擴展性,探討OOD編程方式上的思路。

上一篇:Delphi代碼創建形式規范

下一篇:在Delphi中自己建立交叉表

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色无极影院亚洲| 中文欧美在线视频| 成人www视频在线观看| 日本亚洲欧洲色α| 国产精品久久久久91| 久久久国产影院| 日本精品免费观看| 久久九九精品99国产精品| 亚洲天堂网站在线观看视频| 日韩中文字幕免费| 久久精品99久久香蕉国产色戒| 色哟哟亚洲精品一区二区| 色噜噜狠狠色综合网图区| 少妇av一区二区三区| 日韩一区二区在线视频| 国模叶桐国产精品一区| 国产精品欧美日韩一区二区| 亚洲福利小视频| 久久久精品日本| 国产精品久久久一区| 国产精品网站视频| 色偷偷av一区二区三区乱| 亚洲综合在线小说| 5252色成人免费视频| 亚洲国产精品久久久久秋霞蜜臀| 精品久久久精品| 在线观看视频99| 亚洲国产私拍精品国模在线观看| 国产精品h在线观看| 国产精品国语对白| 欧美日韩另类视频| 91po在线观看91精品国产性色| 日韩欧美在线视频日韩欧美在线视频| 欧美日韩电影在线观看| 日韩电影免费观看在线| 欧美寡妇偷汉性猛交| 国产欧美日韩丝袜精品一区| 国产精品久久久久久久午夜| 97免费在线视频| 日本高清不卡在线| 欧美一级淫片videoshd| 成人做爰www免费看视频网站| 成人黄色av免费在线观看| 亚洲综合成人婷婷小说| 91精品久久久久久久久久久久久久| 欧美国产视频日韩| 欧美性生交大片免网| 国产成人亚洲综合| 亚洲欧美日韩另类| 狠狠色狠狠色综合日日五| 高清欧美性猛交| 姬川优奈aav一区二区| 亚洲成人黄色网址| 欧美性猛交xxxx免费看漫画| 国产91网红主播在线观看| 欧美精品制服第一页| 国产精品久久99久久| 夜夜狂射影院欧美极品| 欧美精品在线极品| 亚洲人成在线一二| 国内精品久久久久久影视8| 亚洲视频电影图片偷拍一区| 亚洲最新av在线网站| 亚洲欧洲在线观看| 欧美日韩激情视频8区| 欧美疯狂做受xxxx高潮| 这里只有视频精品| 在线播放日韩欧美| 懂色aⅴ精品一区二区三区蜜月| 日韩在线激情视频| 欧美电影免费观看大全| 国内精品久久久久久影视8| 精品国产乱码久久久久久婷婷| 国产精品高潮呻吟视频| 91成人天堂久久成人| 国产欧美日韩免费看aⅴ视频| 98精品国产高清在线xxxx天堂| 亚洲国产精品一区二区三区| 日韩欧美国产高清91| 色在人av网站天堂精品| 成人黄色在线免费| 欧美高清第一页| 中文字幕精品www乱入免费视频| 日韩国产精品一区| 国产精品国产三级国产aⅴ浪潮| 18性欧美xxxⅹ性满足| www.xxxx欧美| 欧美亚洲在线播放| 日韩成人中文字幕在线观看| 国产精品一区二区在线| 亚洲字幕一区二区| 亚洲一区二区中文| 欧美日韩激情视频| 日韩免费看的电影电视剧大全| 亚州精品天堂中文字幕| 国产精品视频一区国模私拍| 中文字幕日韩av综合精品| 日韩免费看的电影电视剧大全| 欧美国产日产韩国视频| 久久99国产综合精品女同| 51视频国产精品一区二区| 欧美激情欧美狂野欧美精品| 成人久久精品视频| 国产精品美女免费看| 日韩久久精品电影| 成人黄色大片在线免费观看| 欧美孕妇性xx| 91黑丝高跟在线| 18性欧美xxxⅹ性满足| 亚洲久久久久久久久久久| 久久影视电视剧免费网站清宫辞电视| 国产精品久在线观看| 一区二区欧美激情| 欧美色xxxx| 国产精品久久久久久超碰| 日本亚洲欧美三级| 疯狂做受xxxx欧美肥白少妇| 精品国产一区二区三区久久久| 国产精品日韩av| 91国内产香蕉| 日韩三级成人av网| 欧美成在线视频| 国产精品www色诱视频| 色噜噜国产精品视频一区二区| 在线免费看av不卡| 国产精品视频在线观看| 国产视频自拍一区| 国产精品视频白浆免费视频| 亚洲激情视频在线播放| 色婷婷亚洲mv天堂mv在影片| 一本大道香蕉久在线播放29| 92看片淫黄大片看国产片| 日韩的一区二区| 久久亚洲综合国产精品99麻豆精品福利| 久久全球大尺度高清视频| 2019中文字幕在线免费观看| 欧美成人黑人xx视频免费观看| 国产98色在线| 欧美插天视频在线播放| 国产成人精品一区二区三区| 欧美日韩一区二区精品| 亚洲欧洲午夜一线一品| 日韩成人网免费视频| 久久久久久久久久久av| 亚洲日韩欧美视频一区| 国产欧美一区二区三区视频| 性日韩欧美在线视频| 精品亚洲一区二区三区| 国产mv久久久| 日韩电影在线观看永久视频免费网站| 欧美精品在线免费观看| 日韩欧美一区二区在线| 国产九九精品视频| 亚洲色图综合网| 中文字幕日韩精品有码视频| 亚洲国产小视频在线观看| 欧美有码在线观看| 一区二区三区精品99久久| 久久精品免费电影| 国产精品综合久久久| 久久精品国产清自在天天线| 国产精品久久一区主播| 91手机视频在线观看| 欧美视频国产精品|