JiveJdon Community Forums
在线234人   首页   主题表   培训咨询   标签   查搜   注册    登陆 RSS
首页 » 论坛 » 设计模式、框架和架构
???en_US.forumThreadPrev.name??? 上一主题
RSS google yahoo 365Key网摘 CSDN网摘 添加到百度搜藏 POCO网摘 新浪ViVi QQ网摘
???en_US.forumThreadNext.name??? 下一主题
Go 共有 14 回复(1页) 阅读144次
 发表新帖子   回复该主题贴
VRGL



发表文章:
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
我的一个visitor实作 2003年04月05日 13:50 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
标签     

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);
}
}
banq



发表文章: 11308
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 72人关注
Re: 我的一个visitor实作 2003年04月05日 17:17 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
不错,关键是要结合自己的项目能应用,因为这时你就有两件事要协调和处理,一边是visitor模式各个角色,一边是实际项目的各个角色,如何对号入坐是比较费劲的。
VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
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.
VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
c#版本的 2003年04月06日 17:43 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
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);
}
}
}
VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
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
banq



发表文章: 11308
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 72人关注
Re: vb.net版本的 2003年04月06日 21:51 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
晕。。。佩服
manbaum



发表文章:
注册时间: 2003年03月21日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
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);
}
}

manbaum



发表文章: 36
注册时间: 2003年03月21日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
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);
}
}

VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月07日 18:16 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
gof的visitor接口可以改成函数重载的型式,
我的是用了一个catch-all的visitor接口,
看banq能不能改成非RTTI的型式?:)
VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月07日 21:05 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
使用重载方法的好处是,可以统一用visit方法,
通过传不同参数来完成访问。但哪个程序员偷偷
把以前的类继承结构修改了,添加了一个新类,
那么在访问这个类时,就会出现一个编译错误,
解决办法就是用一个catch-all的visit方法,
给每个继承这个方法的visitor一个缺省的实现,
为了处理新类,写一个新的visitor,用RTTI来
判断(type switch),但如果新类太多就会出现
很长的type switch,也就是visitor模式的缺点,
解决的办法就是大家都不要过于依赖继承,
要prefer compositon to inheritance:)
richardluopeng



发表文章: 71
注册时间: 2002年08月30日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月08日 09:20 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
呵呵,不明白你说的

“catch-all的visitor接口”,呵呵

张二狠



发表文章:
注册时间: 2003年04月10日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月10日 15:19 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
也写点对搂主写的code的理解

一个参观者,一个招待的人
招待的人可以接受参观者并且根据参观者的不同提供各项服务
所以招待者class里面应该定义对于参观者的接受功能,定义
提供的各项服务,

参观者class里面定义可以根据自己的身份去使用(调用)招待者提供的服务的方法

于是
来了一个参观者,来了一个接待者

接待者接待了参观者,并且告诉他所能提供的服务
于是参观者根据自己的身份去选择了某一个服务
。。。。。。故事就这么开始了
张二狠



发表文章: 10
注册时间: 2003年04月10日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月10日 15:31 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
manbaum 的方法实际上变成了一群招待者和一个参观者的问题
这群招待者中的每一个提供一类服务
而参观者根据自己的身份可以去选择某一个招待者去为自己提供服务

那个好?
VRGL



发表文章: 21
注册时间: 2002年09月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月10日 17:44 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
catch-all的visitor可以捕获
所有可能的新增的visitable类,
而无需重新修改所有的visitor类
继承结构,缺点是如果新增的类
很多的话会使用很长的type switch。
richardluopeng



发表文章: 71
注册时间: 2002年08月30日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 我的一个visitor实作 2003年04月11日 13:32 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
hehe ,反对你的说法
标签     
共有 14 回复(1页) Go
???en_US.forumThreadPrev.name??? 上一主题
  Go back to the topic 返回本主题   Go back to the topic listing返回主题列表    返回页首返回页首
???en_US.forumThreadNext.name??? 下一主题
正在读取,请等待...
查询本论坛内 回复超过的热门帖子
标题
 
粗体: [b]文本[/b] 斜体: [i]文本[/i] 下划线 [u]文本[/u] 插入网上的图片 [img]http://wwww.xxxx.com/img.ext[/img] 插入代码 [code]程序代码[/code]  插入url链接 [url]http://url[/url] / [url=http://url]URL加下滑线[/url] 上传图片 word文档 Txt等附件
内容
  提交时自动拷贝以上内容到剪贴板 Ctrl+V可取出;提问题前先查询标签列表

使用帮助 手机m.jdon.com RSS add to google add to yahoo
解惑之道在J道 ,打造中国最具影响力的的软件架构社区 推荐FireFox或Chrome快速浏览本站
OpenSource JIVEJDON Powered by JdonFramework Code © 2002-10 jdon.com

anti spam