涉及角色
1.Visitor 抽象訪問者角色,為該對象結構中具體元素角色聲明一個訪問操作接口。該操作接口的名字和參數標識了傳送訪問請求給具體訪問者的具體元素角色,這樣訪問者就可以通過該元素角色的特定接口直接訪問它。
2.ConcreteVisitor.具體訪問者角色,實現Visitor聲明的接口。
3.Element 定義一個接受訪問操作(accept()),它以一個訪問者(Visitor)作為參數。
4.ConcreteElement 具體元素,實現了抽象元素(Element)所定義的接受操作接口。
5.ObjectStructure 結構對象角色,這是使用訪問者模式必備的角色。它具備以下特性:能枚舉它的元素;可以提供一個高層接口以允許訪問者訪問它的元素;如有需要,可以設計成一個複合對象或者一個聚集(如一個列表或無序集合)。
通用代碼實現
[java]
abstract class Element{ public abstract void accept(IVisitor visitor); public abstract void doSomething();}class ConcreteElement1 extends Element{ public void doSomething(){ System.out.println("這是元素1"); } public void accept(IVisitor visitor){ visitor.visit(this); }}class ConcreteElement2 extends Element{ public void doSomething(){ System.out.println("這是元素2"); } public void accept(IVisitor visitor){ visitor.visit(this); }}interface IVisitor{ public void visit(ConcreteElement1 el1); public void visit(ConcreteElement2 el2);}class Visitor implements IVisitor{ public void visit(ConcreteElement1 el1){ el1.doSomething(); } public void visit(ConcreteElement2 el2){ el2.doSomething(); }}class ObjectStruture{ public static List<Element> getList(){ List<Element>list = new ArrayList<Element>(); Random ran = newRandom(); for(int i = 0 ; i < 10 ; i ++){ int a=ran.nextInt(100); if(a>50){ list.add (newConcreteElement1()); }else{ list.add (newConcreteElement2()); } } return list; }}public class Client{ public static void main (String[]args){ List<Element> list = ObjectStruture.getList(); for(Elemente e:list){ e.accept(new Visitor()); } }}
特點
訪問者模式把數據結構和作用於結構上的操作解
耦合,使得操作集合可相對自由地演化。
訪問者模式適用於數據結構相對穩定算法又易變化的系統。因為訪問者模式使得算法操作增加變得容易。若系統數據結構對象易於變化,經常有新的
數據對象增加進來,則不適合使用訪問者模式。
訪問者模式的優點是增加操作很容易,因為增加操作意味著增加新的訪問者。訪問者模式將有關行為集中到一個訪問者對象中,其改變不影響系統數據結構。其缺點就是增加新的數據結構很困難。
優點
1、符合單一職責原則:凡是適用訪問者模式的場景中,元素類中需要封裝在訪問者中的操作必定是與元素類本身關係不大且是易變的操作,使用訪問者模式一方面符合單一職責原則,另一方面,因為被封裝的操作通常來說都是易變的,所以當發生變化時,就可以在不改變元素類本身的前提下,實現對變化部分的擴展。
2、擴展性良好:元素類可以通過接受不同的訪問者來實現對不同操作的擴展。
適用情況
1、 一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。
2、 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor模式使得你可以將相關的操作集中起來 定義在一個類中。
3、 當該對象結構被很多套用共享時,用Visitor模式讓每個套用僅包含需要用到的操作。
4、定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結構類經常改變,那么可能還是在這些類中定義這些操作較好。