`
cooldesigner
  • 浏览: 67465 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

Visitor

阅读更多

起源<o:p></o:p>

Delphi中的Visitor模式在基本Visitor模式进行了扩展。更多Visitor模式的资料请参 [Gam+, pages 331..344].<o:p></o:p>

目的

表示一个作用于某个对象结构的中和元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。<o:p></o:p>

 [Gam+, page 331].

动机<o:p></o:p>

考虑一个面向对象的建模工具比如说Rational RoseModelMaker,它将一个模型表示为类和类的成员。

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

这些操作大多对不同的成员进行不同的操作。它将成员分成字段(fields)、方法(methods)、

属性(properties)。因些我们必须建立专门处理字段的类,专门处理methods的类等等。成员类的集合当然依赖被编译的语言。但对于一给定语言变化不大。

 <o:p></o:p>

<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> </v:shapetype> <o:p></o:p>

如图显示了部分成员类的框架。问题产生了,如果我将所有这些操作分散到不同的成员类,

将会导致整个系统难于理解,修改,维护。将类代码生成与类成员检查放在一起,将产生混乱。些外加入新的操作时要重新编译的有的类(至少也重新编译所有的相关的系)。有个办法:你可能独立的增加一个新的操作,并这个成员类独立如作用于其上的操作。

要实现上述两个目标,我们可以将每个类中相关操作包装在一上独立的对象(称为visitor

并在遍历类成员列表时将此对象传递给当前成员。当一个成员‘接受’ 访问,该成员向访问者发送包含自身信息的请求。该成员请自本身作为一个参数。访问者执行这些操作。

例如:一个不使用访问者的代码生成器可能会通成员类的抽象的方法:TMember.WriteInterfaceCode(Output: TStream)生成代码。每一个成员都会调用WriteInterfaceCode生成适当的输出代码。如果通过访问者来生成代码,则会创建一个TinterfaceCodeVisitor对象,并在成员列表上调用参数为访问对象的AcceptVisitor方法。每一个在员在实现AcceptVisitor将会回调visitor一个字段将调用访问者的VisitField方法,而一个方法则调用VisitMethod方法。这样,以前类TfieldWriteInterfaceCode操作现在成为TinterfaceCodeVisitorVisitField操作。<o:p></o:p>

 <o:p></o:p>

为使访问者不仅仅只做代码生成,我们需要所有的成员列表的访问者有一个抽象的父类TmemberVisitorTmemberVisitor必须为每一个成员定义一种方法。一个需要将成员输出为HTML格式的应用将定义TmemberVisitor新的子类,并不再需要在成员类中增加与特定应用相关的代码。Visitor模式将每个操作封装在一个相关的Visitor<o:p></o:p>

 <o:p></o:p>

使用Visitor模式,必须定义两个层次的类:一个应于接受操作的元素(Tmember层次)另一个定义于对元素的操作(TmemberVisitor 层次)。增加一个新的操作时只需给访问者层次增加一个新的子类。我可能简单的定义新的TmemberVisitor子类以增加新的功能。

<o:p></o:p>

应用

下面的代码演示上面描述的类TmemberVisitor模式的应用

 <o:p></o:p>

type

  TMember = class (TObject)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); virtual;

  end;

 <o:p></o:p>

  TField = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 <o:p></o:p>

  TMethod = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 <o:p></o:p>

  TProperty = class (TMember)

  public

    procedure AcceptMemberVisitor(Visitor: TMemberVisitor); override;

  end;

 <o:p></o:p>

  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;

 <o:p></o:p>

implementation

 <o:p></o:p>

{ TMember }

 <o:p></o:p>

begin

  Visitor.VisitMember(Self);

end;

 <o:p></o:p>

{ TField }

procedure TField.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

end;

 <o:p></o:p>

{ TMethod }

procedure TMethod.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

  Visitor.VisitMethod(Self);

end;

 <o:p></o:p>

{ TProperty }

procedure TProperty.AcceptMemberVisitor(Visitor: TMemberVisitor);

begin

  Visitor.VisitProperty(Self);

end;

 <o:p></o:p>

{ TMemberVisitor }

procedure TMemberVisitor.VisitField(Instance: TField);

begin

end;

 <o:p></o:p>

procedure TMemberVisitor.VisitMember(Instance: TMember);

begin

end;

 <o:p></o:p>

procedure TMemberVisitor.VisitMethod(Instance: TMethod);

begin

end;

 <o:p></o:p>

procedure TMemberVisitor.VisitProperty(Instance: TProperty);

begin

end;

 <o:p></o:p>

说明:

·      TMember, TField, TMethod Tproperty都实现了AcceptMemberVisitor方法. 这些方法都嵌入模式中

·      TMemberVisitor 类实现了VisitMember, VisitField方法。TmemberVisitor是一个抽象的类,它所有的方法由具体的子类实现。

下面是一个简单的代码生成器的实现。

代码介绍:

·      TCodeGenerationVisitor 是一个用于实现成员的代码生成器的访问者。

·      访问者定义了一个上下文相关的属性:Output: TTextStream,

·       它必须在VisitXXX调用前被定,如:DrawingVisitor典型的需要一个包括canvas的上下文,来支持画图操作。上下文在遍历整个member对列前赋予了代码生成器。

·      代码生成器将整结的生成的类的所有代码

 <o:p></o:p>

要真正的了解Visitor模式,你可执行这个例子 ,并进一步的学习双分派机制: accept/visit.

 <o:p></o:p>

unit CodeGenerators;

 <o:p></o:p>

interface

 <o:p></o:p>

uses Classes, TextStreams;

 <o:p></o:p>

type

 <o:p></o:p>

  TCodeGenerator = class (TObject)

  public

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

  end;

 <o:p></o:p>

implementation

 <o:p></o:p>

uses Members;

 <o:p></o:p>

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;

 <o:p></o:p>

 <o:p></o:p>

{ TCodeGenerationVisitor }

procedure TCodeGenerationVisitor.VisitField(Instance: TField);

begin

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

end;

 <o:p></o:p>

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 := '';

  {代码不完整,现足以演示Tmethod代码生成 }

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

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

end;

 <o:p></o:p>

procedure TCodeGenerationVisitor.VisitProperty(Instance: TProperty);

begin

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

                    [Instance.Name, Instance.DataName,

                     Instance.ReadSpecifier, Instance.WriteSpecifier]);

end;

 <o:p></o:p>

{ TCodeGenerator }

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

var

  I: Integer;

begin

  {写入类定义 }

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

 

 <o:p></o:p>

  {好! 加入代码生成器的访问者}

  Visitor := TCodeGenerationVisitor.Create;

  Try

    {记住为访问都提供上下文,以便更好的访问VisitXXX方法。}

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

      { 代码的具体段,好事情发生了}

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

  finally

    Visitor.Free;

  end;

  {类成员的代码生成完毕}

  Output.WriteLine('end;');

end;

分享到:
评论

相关推荐

    设计模式C++学习之访问者模式(Visitor)

    访问者模式(Visitor)是一种行为设计模式,它允许在不修改对象结构的前提下向对象结构中的元素添加新的操作。这种模式将算法与数据结构分离,使得算法可以独立于数据结构进行变化,增强了系统的可扩展性。 在C++中...

    设计模式系列之visitor

    本篇文章将聚焦于"访问者(Visitor)"设计模式,这是一种行为设计模式,用于在不修改对象结构的情况下,为对象添加新的操作。接下来我们将深入探讨该模式的概念、实现及应用场景。 访问者模式的核心思想是将数据...

    访问者模式VisitorPattern

    **访问者模式(VisitorPattern)** 访问者模式是一种行为设计模式,它使你能在不修改对象结构的前提下向对象添加新的操作。这种模式常用于处理具有复杂逻辑的对象结构,特别是当你需要对这些对象进行多态操作时。访问...

    Laravel开发-visitor

    在本文中,我们将深入探讨如何使用 Laravel 框架开发一个名为 "visitor" 的系统,该系统能够跟踪和记录网站的访问者行为,包括页面点击量,并为 Laravel 5 应用程序提供自定义的访问计数器功能。Laravel 是一款流行...

    AXS Visitor Tracking System

    AXS Visitor Tracking System 是一款专为网站数据分析设计的统计与访客跟踪程序。它提供了丰富的功能,帮助网站管理员深入了解用户行为、流量来源以及网站性能,从而优化网站内容和营销策略。下面将详细介绍这款系统...

    基于visitor模式和访问者模式的表达式树_求值引擎

    本项目基于“visitor模式”和“访问者模式”,实现了用于计算表达式的求值引擎,这涉及到一种将数学表达式转化为数据结构(表达式树)的方法,然后通过遍历该树来执行计算。下面我们将详细探讨这些概念。 1. **...

    设计模式之访问者模式(Visitor)

    **访问者模式(Visitor)详解** 访问者模式是一种行为设计模式,它使你可以在不修改对象结构的情况下,为对象添加新的操作。这种模式的核心在于将数据结构与对这些数据的操作解耦,使得增加新的操作变得容易,同时...

    Laravel开发-visitor-log

    在本文中,我们将深入探讨如何使用Laravel框架开发一个访客日志系统,特别是"visitor-log"项目。Laravel 4是这个项目的基础,它是一个功能强大、优雅的PHP web应用开发框架,提供了丰富的工具来简化开发过程,使得...

    C++ Visitor模式

    **C++ Visitor模式详解** Visitor模式是设计模式中的一种行为模式,它在对象结构中引入了一个访问者角色,使得访问者能够对结构中的每个元素进行操作,而不改变元素本身的行为。这种模式允许我们在不修改已有类的...

    Visitor模式Visitor模式

    Visitor 模式 Visitor 模式是一种行为型设计模式,它允许在不修改已有的类层次的情况下,增加新的操作或行为。这种模式可以使得开发者在不改变原有类层次的情况下,能够对对象进行不同的处理。 从给定的文件信息...

    Visitor模式

    访问者模式(Visitor Pattern)是一种行为设计模式,它使你能在不修改对象结构的前提下,为对象添加新的操作。这种模式在处理具有复杂逻辑和多种类型的对象结构时特别有用,因为它允许你在不改变原有结构的情况下,...

    C#面向对象设计模式纵横谈(24):(行为型模式) Visitor 访问者模式

    ### C#面向对象设计模式纵横谈(24):(行为型模式) Visitor 访问者模式 #### 概述 在本篇文章中,我们将深入探讨面向对象设计模式中的一个非常重要的模式——**Visitor(访问者)模式**。此模式属于行为型模式的一...

    试试visitor设计模式

    也许最开始出现这种模式,是因为另外的原因: 我有一堆数据放在一个库里头,不想让其它人拿着, 如果你要用数据干活,那你就把函数指针给我,我来替你使用这个数据。...然后人们就说,这是visitor模式。

    visitor pattern

    **访客模式(Visitor Pattern)** 访客模式是一种行为设计模式,它允许在不修改对象结构的情况下,为对象增加新的操作。这种模式常用于将算法与数据结构分离,使得算法可以独立于数据结构进行变化。在软件开发中,当...

    Visitor校验器 域对象级别上验证(完整示例源码)

    struts2中Visitor校验器以及域对象级别上验证和使用上下文优化的使用,我自己写的一个完整代码,详细的展示了如何使用Visitor校验器以及怎样在域对象上验证和注意事项,代码解压后可以直接部署到MyEclipse上运行,...

    Visitor TT1 BRK

    Visitor TT1 BRK

    visitor.js.zip

    visitor.js这个js文件能提供你关于你的网站的访客的详细信息(比如他在哪个城市,最后访问日期等等)。 该软件已改名为 session.js

    C#设计模式之Visitor

    **C#设计模式之Visitor** **一、设计模式概述** 设计模式是软件开发中的经验总结,它提供了解决常见问题的可复用解决方案。在C#编程中,设计模式可以帮助我们编写更灵活、可扩展和易于维护的代码。"Visitor"(访问...

Global site tag (gtag.js) - Google Analytics