|
|
|
public interface Visitable { void accept(Visitor visitor); }
public interface Visitor { void visit(Visitable visitable); }
public class VisitableA implements Visitable { public String Call(){ return "AAA"; } public void accept(Visitor visitor) { visitor.visit(this); } }
public class VisitorA implements Visitor { public void visit(Visitable visitable) { if (visitable instanceof VisitableA) { System.out.println(((VisitableA)visitable).Call()); } }
}
public class Client{ public static void main(String args[]) { Visitor visitor=new VisitorA(); Visitable visitable=new VisitableA(); visitable.accept(visitor); } }
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月05日 17:17
|
|
|
不错,关键是要结合自己的项目能应用,因为这时你就有两件事要协调和处理,一边是visitor模式各个角色,一边是实际项目的各个角色,如何对号入坐是比较费劲的。
|
|
|
|
|
|
delphi版本的
|
2003年04月06日 17:43
|
|
|
delphi版本的: unit UVisitor; interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, forms, Dialogs, StdCtrls;
type
Tform1 = class(Tform) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var form1: Tform1;
implementation
type TVisitor=class; TVisitable=class procedure accept(visitor:TVisitor);virtual;abstract; end; TVisitor=class procedure visit(visitable:TVisitable);virtual;abstract; end; TVisitableA=class(TVisitable) public procedure accept(visitor:TVisitor);override; function Call():string; end; TVisitorA=class(TVisitor) public procedure visit(visitable:TVisitable);override; end;
{$R *.dfm}
{ TVisitableA }
procedure TVisitableA.accept(visitor: TVisitor); begin inherited; visitor.visit(self); end;
function TVisitableA.Call: string; begin Result:='AAA'; end;
{ TVisitorA }
procedure TVisitorA.visit(visitable: TVisitable); begin inherited; if visitable is TVisitableA then showmessage(TVisitableA(visitable).Call); end;
procedure Tform1.Button1Click(Sender: TObject); var v:TVisitor; vb:TVisitable; begin v:=TVisitorA.Create; vb:=TVisitableA.Create; vb.accept(v); v.Free; vb.Free; end;
end.
|
|
|
|
|
|
c#版本的: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.forms; using System.Data; namespace WindowsApplication2 { /// /// form1 的摘要说明。 /// public interface IVisitable { void accept(IVisitor visitor); }
public interface IVisitor { void visit(IVisitable visitable); }
public class VisitorA:IVisitor { public void visit(IVisitable visitable){ if (visitable is VisitableA){ MessageBox.Show(((VisitableA)visitable).Call(),""); } } }
public class VisitableA:IVisitable { public String Call() { return "AAA"; } public void accept(IVisitor visitor){ visitor.visit(this); } }
/// public class form1 : System.Windows.forms.form { private System.Windows.forms.Button button1; /// /// 必需的设计器变量。 /// private System.ComponentModel.Container components = null;
public form1() { // // Windows 窗体设计器支持所必需的 // InitializeComponent();
// // TODO: 在 InitializeComponent 调用后添加任何构造函数代码 // }
/// /// 清理所有正在使用的资源。 /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Windows form Designer generated code /// /// 设计器支持所需的方法 - 不要使用代码编辑器修改 /// 此方法的内容。 /// private void InitializeComponent() { this.button1 = new System.Windows.forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(80, 72); this.button1.Name = "button1"; this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.Click += new System.EventHandler(this.button1_Click); // // form1 // this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); this.ClientSize = new System.Drawing.Size(292, 272); this.Controls.AddRange(new System.Windows.forms.Control[] { this.button1}); this.Name = "form1"; this.Text = "form1"; this.ResumeLayout(false);
} #endregion
/// /// 应用程序的主入口点。 /// [STAThread] static void Main() { Application.Run(new form1()); }
private void button1_Click(object sender, System.EventArgs e) { IVisitor v=new VisitorA(); IVisitable vb=new VisitableA(); vb.accept(v); } } }
|
|
|
|
|
|
vb.net版本的
|
2003年04月06日 17:44
|
|
|
vb.net版本的: Public Class form1 Inherits System.Windows.forms.form Public MustInherit Class Visitor Public MustOverride Sub visit(ByRef vb As Visitable) End Class
Public MustInherit Class Visitable Public MustOverride Sub accept(ByRef v As Visitor) End Class
Public Class VisitorA Inherits Visitor Public Overrides Sub visit(ByRef vb As Visitable) If vb.GetType Is GetType(VisitableA) Then MessageBox.Show(CType(vb, VisitableA).CallOp, "") End If End Sub End Class
Public Class VisitableA Inherits Visitable Public Function CallOp() As String Return "AAA" End Function Public Overrides Sub accept(ByRef v As Visitor) v.visit(Me) End Sub End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim vb As Visitable Dim v As Visitor vb = New VisitableA() v = New VisitorA() vb.accept(v) vb = Nothing v = Nothing End Sub End Class
|
|
|
|
|
|
Re: vb.net版本的
|
2003年04月06日 21:51
|
|
|
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月07日 11:55
|
|
|
使用 if (visitable instanceof VisitableA) 的方式,已经是在使用 RTTI 了。而 GoF 的 Visitor 实现并没有使用 RTTI。按你的例子,改写如下:
public interface Visitable { void accept(Visitor visitor); }
public class VisitableA implements Visitable { public String CallA() { return "AAA"; }
public void accept(Visitor visitor) { visitor.VisitVisitableA(this); } }
public class VisitableB implements Visitable { public String CallB() { return "BBB"; }
public void accept(Visitor visitor) { visitor.VisitVisitableB(this); } }
public class Visitor { public void VisitVisitableA(VisitableA va) { String s = va.CallA(); System.out.println(s); } public void VisitVisitableB(VisitableB vb) { String s = vb.CallB(); System.out.println(s); } }
|
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月07日 12:12
|
|
|
GoF的原文 Visitor: 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
是不是这样的实现才能符合这段话?关键是“不改变各元素的类”。
public class A { public String CallA() { return "AAA"; } }
public class B { public String CallB() { return "BBB"; } }
public interface Visitable { void accept(Visitor visitor); }
public class VisitableA extends A implements Visitable { public void accept(Visitor visitor) { visitor.VisitA(this); } }
public class VisitableB extends B implements Visitable { public void accept(Visitor visitor) { visitor.VisitB(this); } }
public class Visitor { public void VisitA(A a) { String s = a.CallA(); System.out.println(s); } public void VisitB(B b) { String s = b.CallB(); System.out.println(s); } }
|
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月07日 18:16
|
|
|
gof的visitor接口可以改成函数重载的型式, 我的是用了一个catch-all的visitor接口, 看banq能不能改成非RTTI的型式?:)
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月07日 21:05
|
|
|
使用重载方法的好处是,可以统一用visit方法, 通过传不同参数来完成访问。但哪个程序员偷偷 把以前的类继承结构修改了,添加了一个新类, 那么在访问这个类时,就会出现一个编译错误, 解决办法就是用一个catch-all的visit方法, 给每个继承这个方法的visitor一个缺省的实现, 为了处理新类,写一个新的visitor,用RTTI来 判断(type switch),但如果新类太多就会出现 很长的type switch,也就是visitor模式的缺点, 解决的办法就是大家都不要过于依赖继承, 要prefer compositon to inheritance:)
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月08日 09:20
|
|
|
呵呵,不明白你说的
“catch-all的visitor接口”,呵呵
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月10日 15:19
|
|
|
也写点对搂主写的code的理解
一个参观者,一个招待的人 招待的人可以接受参观者并且根据参观者的不同提供各项服务 所以招待者class里面应该定义对于参观者的接受功能,定义 提供的各项服务,
参观者class里面定义可以根据自己的身份去使用(调用)招待者提供的服务的方法
于是 来了一个参观者,来了一个接待者
接待者接待了参观者,并且告诉他所能提供的服务 于是参观者根据自己的身份去选择了某一个服务 。。。。。。故事就这么开始了
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月10日 15:31
|
|
|
manbaum 的方法实际上变成了一群招待者和一个参观者的问题 这群招待者中的每一个提供一类服务 而参观者根据自己的身份可以去选择某一个招待者去为自己提供服务
那个好?
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月10日 17:44
|
|
|
catch-all的visitor可以捕获 所有可能的新增的visitable类, 而无需重新修改所有的visitor类 继承结构,缺点是如果新增的类 很多的话会使用很长的type switch。
|
|
|
|
|
|
Re: 我的一个visitor实作
|
2003年04月11日 13:32
|
|
|
|
|
|
|