C11) Visitor(访问者模式) 定义:描述一个作用于对象结构中的元素的操作,访问者模式使得不改变所操作元素的类就可以定义一个新的操作。 这个模式,在客户端和被其操作的对象之间建立了一个访问者,客户端通过访问者访问被操作对象,一方面降低耦合,另一方面方便改变操作的动作。非常适合应用在有多种类型的被操作对象的场合,比如集合对象。 现在假设有一个存放备注集合的对象,其中可能的元素有字条MemoStr、日期MemoDate、金额MemoDbl,那通常会用的方法如下,定义3个对象 public class MemoStr { private int memoId; private String memo; } public class MemoDate { private int memoId; private Date memo; } public class MemoDbl { private int memoId; private double memo; } 客户端访问 Collection memos = new ArrayList(); memos.add(new MemoStr(1,"明天休息")); memos.add(new MemoDate(2,new Date())); memos.add(new MemoDbl(3,1136.5));
Iterator itr = memos.Iterator(); while (itr.hasNext()) { Object o = itr.next(); if (o instanceof MemoStr) { System.out.println(((MemoStr)o).getMemo()); }else if (itr.next() instanceof MemoDate) { SimpleDateFormat df = new SimpleDateFormat("YY/MM/DD"); System.out.println(df.format(((MemoDate)o).getMemo())); }else if (itr.next() instanceof MemoDbl) { DecimalFormat df = new DecimalFormat("#,#0.00"); System.out.println(df.format(((MemoDbl)o).getMemo())); } } 以上是通常的做法,来看看使用访问者模式带来的变化。 首先,定一个接口和一个访问者对象 public interface Visitable { public void accept(Visitor visitor); } public class Visitor { public void visitShow(MemoStr str) { System.out.println(str.getMemo()); } public void visitShow(MemoDate day) { SimpleDateFormat df = new SimpleDateFormat("YY/MM/DD"); System.out.println(df.format(day.getMemo())); } public void visitShow(MemoDbl dbl) { DecimalFormat df = new DecimalFormat("#,#0.00"); System.out.println(df.format(dbl.getMemo())); } } MemoStr等3个对象必须实现Visitable接口,以MemoStr为例 public class MemoStr implements Visitable { private int memoId; private String memo; public void accept(Visitor visitor) { visitor.visitShow(this) } } 完成后,客户端的调用变为 Visitor visitor = new Visitor(); Iterator itr = memos.Iterator(); while (itr.hasNext()) { Object o = itr.next(); if (o instanceof Visitable) { ((Visitable)o).accept(visitor); } } 将对象和操作分离,在需要修改操作部分时,仅改变Visitor就可以完成对所有客户端的修改,而当添加了新的元素如MemoTel等时,也只需在Visitor中添加访问方法。这样就完成了访问者模式,在不知道对象类型的情况下,用不着猜测对象的类型,直接让对象来告诉我们该如何操作它。由于是面向接口,可扩展性非常好。
参考: 1、 http://www./designpatterns/visitor.htm(中文、java实例) 2、 http://www./Patterns/PatternVisitor.aspx(英文、C#实例、UML) 3、 http://www.caterpillar./PmWiki/pmwiki.php/DesignPattern/VisitorPattern(中文、java实例、UML)推荐 4、 http://www./tech/DesignPattern/Visitor.html(日文、java实例、UML)推荐
|