Visitor模式" />

麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Delphi > 正文

設(shè)計(jì)模式、用Delphi描述-->Visitor模式

2019-11-18 18:45:32
字體:
供稿:網(wǎng)友

Visitor 模式

起源

Delphi中的Visitor模式在基本Visitor模式進(jìn)行了擴(kuò)展。更多Visitor模式的資料請(qǐng)參 [Gam+, pages 331..344].

目的

表示一個(gè)作用于某個(gè)對(duì)象結(jié)構(gòu)的中和元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

 [Gam+, page 331].

動(dòng)機(jī)

考慮一個(gè)面向?qū)ο蟮慕9ぞ?/SPAN>比如說Rational RoseModelMaker,它將一個(gè)模型表示為類和類的成員。

在建模工具上提供了許多操作成員功能,比如:列表類的所有成員、生成類的代碼框架、反向工程等。

這些操作大多對(duì)不同的成員進(jìn)行不同的操作。它將成員分成字段(fields)、方法(methods)、

屬性(PRoperties)。因些我們必須建立專門處理字段的類,專門處理methods的類等等。成員類的集合當(dāng)然依賴被編譯的語言。但對(duì)于一給定語言變化不大。

 

 

 

如圖顯示了部分成員類的框架。問題產(chǎn)生了,如果我將所有這些操作分散到不同的成員類,

將會(huì)導(dǎo)致整個(gè)系統(tǒng)難于理解,修改,維護(hù)。將類代碼生成與類成員檢查放在一起,將產(chǎn)生混亂。些外加入新的操作時(shí)要重新編譯的有的類(至少也重新編譯所有的相關(guān)的系)。有個(gè)辦法:你可能獨(dú)立的增加一個(gè)新的操作,并這個(gè)成員類獨(dú)立如作用于其上的操作。

要實(shí)現(xiàn)上述兩個(gè)目標(biāo),我們可以將每個(gè)類中相關(guān)操作包裝在一上獨(dú)立的對(duì)象(稱為visitor

并在遍歷類成員列表時(shí)將此對(duì)象傳遞給當(dāng)前成員。當(dāng)一個(gè)成員‘接受’ 訪問,該成員向訪問者發(fā)送包含自身信息的請(qǐng)求。該成員請(qǐng)自本身作為一個(gè)參數(shù)。訪問者執(zhí)行這些操作。

例如:一個(gè)不使用訪問者的代碼生成器可能會(huì)通成員類的抽象的方法:TMember.WriteInterfaceCode(Output: TStream)生成代碼。每一個(gè)成員都會(huì)調(diào)用WriteInterfaceCode生成適當(dāng)?shù)妮敵龃a。如果通過訪問者來生成代碼,則會(huì)創(chuàng)建一個(gè)TinterfaceCodeVisitor對(duì)象,并在成員列表上調(diào)用參數(shù)為訪問對(duì)象的AcceptVisitor方法。每一個(gè)在員在實(shí)現(xiàn)AcceptVisitor將會(huì)回調(diào)visitor一個(gè)字段將調(diào)用訪問者的VisitField方法,而一個(gè)方法則調(diào)用VisitMethod方法。這樣,以前類TfieldWriteInterfaceCode操作現(xiàn)在成為TinterfaceCodeVisitorVisitField操作。

 

為使訪問者不僅僅只做代碼生成,我們需要所有的成員列表的訪問者有一個(gè)抽象的父類TmemberVisitorTmemberVisitor必須為每一個(gè)成員定義一種方法。一個(gè)需要將成員輸出為HTML格式的應(yīng)用將定義TmemberVisitor新的子類,并不再需要在成員類中增加與特定應(yīng)用相關(guān)的代碼。Visitor模式將每個(gè)操作封裝在一個(gè)相關(guān)的Visitor

 


 

 

 

使用Visitor模式,必須定義兩個(gè)層次的類:一個(gè)應(yīng)于接受操作的元素(Tmember層次)另一個(gè)定義于對(duì)元素的操作(TmemberVisitor 層次)。增加一個(gè)新的操作時(shí)只需給訪問者層次增加一個(gè)新的子類。我可能簡(jiǎn)單的定義新的TmemberVisitor子類以增加新的功能。

 

應(yīng)用

下面的代碼演示上面描述的類TmemberVisitor模式的應(yīng)用

 

type

  TMember = class (TObject)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); virtual;

  end;

 

  TField = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 

  TMethod = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 

  TProperty = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 

  TMemberVisitor = class (TObject)

  public

    procedure VisitField(Instance: TField); virtual;

    procedure VisitMember(Instance: TMember); virtual;

    procedure VisitMethod(Instance: TMethod); virtual;

    procedure VisitProperty(Instance: TProperty); virtual;

  end;

 

implementation

 

{ TMember }

 

begin

  Visitor.VisitMember(Self);

end;

 

{ TField }

procedure TField.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

end;

 

{ TMethod }

procedure TMethod.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

  Visitor.VisitMethod(Self);

end;

 

{ TProperty }

procedure TProperty.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

  Visitor.VisitProperty(Self);

end;

 

{ TMemberVisitor }

procedure TMemberVisitor.VisitField(Instance: TField);

begin

end;

 

procedure TMemberVisitor.VisitMember(Instance: TMember);

begin

end;

 

procedure TMemberVisitor.VisitMethod(Instance: TMethod);

begin

end;

 

procedure TMemberVisitor.VisitProperty(Instance: TProperty);

begin

end;

 

說明:

?      TMember, TField, TMethod Tproperty都實(shí)現(xiàn)了AcceptMemberVisitor方法. 這些方法都嵌入模式中

?      TMemberVisitor 類實(shí)現(xiàn)了VisitMember, VisitField方法。TmemberVisitor是一個(gè)抽象的類,它所有的方法由具體的子類實(shí)現(xiàn)。

下面是一個(gè)簡(jiǎn)單的代碼生成器的實(shí)現(xiàn)。

代碼介紹:

?      TCodeGenerationVisitor 是一個(gè)用于實(shí)現(xiàn)成員的代碼生成器的訪問者。

?      訪問者定義了一個(gè)上下文相關(guān)的屬性:Output: TTextStream,

?       它必須在VisitXXX調(diào)用前被定,如:DrawingVisitor典型的需要一個(gè)包括canvas的上下文,來支持畫圖操作。上下文在遍歷整個(gè)member對(duì)列前賦予了代碼生成器。

?      代碼生成器將整結(jié)的生成的類的所有代碼

 

要真正的了解Visitor模式,你可執(zhí)行這個(gè)例子 ,并進(jìn)一步的學(xué)習(xí)雙分派機(jī)制: accept/visit.

 

unit CodeGenerators;

 

interface

 

uses Classes, TextStreams;

 

type

 

  TCodeGenerator = class (TObject)

  public

    procedure Generate(Members: TList; Output: TTextStream);

  end;

 

implementation

 

uses Members;

 

type

  TCodeGenerationVisitor = class (TMemberVisitor)

  private

    FOutput: TTextStream;

  public

    procedure VisitField(Instance: TField); override;

    procedure VisitMethod(Instance: TMethod); override;

    procedure VisitProperty(Instance: TProperty); override;

    property Output: TTextStream read FOutput write FOutput;

  end;

 

 

{ TCodeGenerationVisitor }

procedure TCodeGenerationVisitor.VisitField(Instance: TField);

begin

  Output.WriteLnFmt('  %s: %s;', [Instance.Name, Instance.DataName]);

end;

 

procedure TCodeGenerationVisitor.VisitMethod(Instance: TMethod);

var

  MKStr, DTStr: string;

begin

  case Instance.MethodKind of

    mkConstructor: MKStr := 'constructor';

    mkDestructor: MKStr := 'destructor';

    mkProcedure: MKStr := 'procedure';

    mkFuntion: MKStr := 'function';

  end;

  if Instance.MethodKind = mkFunction then

    DTStr := ': ' + Instance.DataName

  else

    DTStr := ';

  {代碼不完整,現(xiàn)足以演示Tmethod代碼生成 }

  Output.WriteLnFmt('  %s %s%s%s;'

                    [MKStr, Instance.Name, Instance.Parameters, DTStr]);

end;

 

procedure TCodeGenerationVisitor.VisitProperty(Instance: TProperty);

begin

  Output.WriteLnFmt('  property %s: %s read %s write %s;',

                    [Instance.Name, Instance.DataName,

                     Instance.ReadSpecifier, Instance.WriteSpecifier]);

end;

 

{ TCodeGenerator }

procedure TCodeGenerator.Generate(Members: TList; Output: TTextStream);

var

  I: Integer;

begin

  {寫入類定義 }

  Output.WriteLine('TSample = class (TObject)');

 

 

  {好! 加入代碼生成器的訪問者}

  Visitor := TCodeGenerationVisitor.Create;

  Try

    {記住為訪問都提供上下文,以便更好的訪問VisitXXX方法。}

    for I := 0 to Members.Count - 1 do

      { 代碼的具體段,好事情發(fā)生了}

      TMember(Members[I]).AcceptMemberVisitor(Visitor);

  finally

    Visitor.Free;

  end;

  {類成員的代碼生成完畢}

  Output.WriteLine('end;');

end;

 

Delphi實(shí)例

正在組織

//很多摘自《設(shè)計(jì)模式》,


上一篇:Delphi報(bào)表控件----SReport3強(qiáng)大易用穩(wěn)定與最終用戶交互良好(新)

下一篇:Delphi命令行參數(shù)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 激情亚洲一区二区三区 | 蜜桃网在线 | 日韩一级精品 | 欧美a∨一区二区三区久久黄 | 亚洲国产精久久久久久久 | 曰批全过程120分钟免费69 | a级高清免费毛片av在线 | 精品国产高清一区二区三区 | 欧美激情首页 | 一级免费特黄视频 | 国产免费黄网 | 色婷婷久久一区二区 | 在线播放黄色网址 | 日韩一级电影在线观看 | 羞羞视频一区二区 | av之家在线观看 | 欧美高清一级片 | 久久人人爽人人爽人人片av高清 | 777zyz色资源站在线观看 | 国产羞羞视频在线观看免费应用 | 黄色网址免费入口 | 久久精品无码一区二区三区 | 成人福利视频 | 超碰97人人艹 | 桥本有菜免费av一区二区三区 | 色淫影院 | 日韩精品中文字幕在线播放 | 国产女同玩人妖 | 成人三级电影网站 | 黑人操穴 | 国产乱淫a∨片免费观看 | 婷婷久久综合九色综合色多多蜜臀 | 毛片在哪看 | 在线播放免费播放av片 | 国产深夜福利视频在线播放 | 欧美aaaaa一级毛片在线 | 日韩av片网站 | 久久精品亚洲欧美日韩精品中文字幕 | 国产免费观看电影网站 | 国产成人在线观看免费 | 91精品久久久久久 |