C11) Visitor(訪問(wèn)者模式) 定義:描述一個(gè)作用于對(duì)象結(jié)構(gòu)中的元素的操作,訪問(wèn)者模式使得不改變所操作元素的類就可以定義一個(gè)新的操作。 這個(gè)模式,在客戶端和被其操作的對(duì)象之間建立了一個(gè)訪問(wèn)者,客戶端通過(guò)訪問(wèn)者訪問(wèn)被操作對(duì)象,一方面降低耦合,另一方面方便改變操作的動(dòng)作。非常適合應(yīng)用在有多種類型的被操作對(duì)象的場(chǎng)合,比如集合對(duì)象。 現(xiàn)在假設(shè)有一個(gè)存放備注集合的對(duì)象,其中可能的元素有字條MemoStr、日期MemoDate、金額MemoDbl,那通常會(huì)用的方法如下,定義3個(gè)對(duì)象 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; } 客戶端訪問(wèn) 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())); } } 以上是通常的做法,來(lái)看看使用訪問(wèn)者模式帶來(lái)的變化。 首先,定一個(gè)接口和一個(gè)訪問(wèn)者對(duì)象 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個(gè)對(duì)象必須實(shí)現(xiàn)Visitable接口,以MemoStr為例 public class MemoStr implements Visitable { private int memoId; private String memo; public void accept(Visitor visitor) { visitor.visitShow(this) } } 完成后,客戶端的調(diào)用變?yōu)?BR> Visitor visitor = new Visitor(); Iterator itr = memos.Iterator(); while (itr.hasNext()) { Object o = itr.next(); if (o instanceof Visitable) { ((Visitable)o).accept(visitor); } } 將對(duì)象和操作分離,在需要修改操作部分時(shí),僅改變Visitor就可以完成對(duì)所有客戶端的修改,而當(dāng)添加了新的元素如MemoTel等時(shí),也只需在Visitor中添加訪問(wèn)方法。這樣就完成了訪問(wèn)者模式,在不知道對(duì)象類型的情況下,用不著猜測(cè)對(duì)象的類型,直接讓對(duì)象來(lái)告訴我們?cè)撊绾尾僮魉?。由于是面向接口,可擴(kuò)展性非常好。
參考: 1、 http://www./designpatterns/visitor.htm(中文、java實(shí)例) 2、 http://www./Patterns/PatternVisitor.aspx(英文、C#實(shí)例、UML) 3、 http://www.caterpillar./PmWiki/pmwiki.php/DesignPattern/VisitorPattern(中文、java實(shí)例、UML)推薦 4、 http://www./tech/DesignPattern/Visitor.html(日文、java實(shí)例、UML)推薦
|