行爲模式---之--訪問者模式

所謂雙分派,就是根據方法的接收者以及某一個參量的類型的不一樣而執行不一樣的代碼。Java語言以方法重載的試支持靜態的多分派,而經過方法的重寫支持動態的單分派
 
訪問者模式是對象的行爲模式。訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操做。一旦這些操做須要修改的話,接受這個操做的數據結構則能夠保持不變。
 
    訪問者模式適用於數據結構相對未定的系統,它把數據結構和做用於結構之上的操做之間的耦合解脫開,使得操做集合能夠相對自由地演化。
 
所涉及角色:
1.抽象訪問者(Visitor)角色:聲明瞭一個或多個訪問操做,造成全部的具體元素角色必須實現的接口
2.具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色所聲明的接口,也就是抽象訪問者所聲明的各個訪問操做。
3.抽象節點(Node)角色:聲明一個接受操做,接受一個訪問者對象做爲一個參量
4.具體節點(Node)角色:實現抽象元素所規定的接受操做
5.結構對象(ObjectStructure)角色:有以下責任,能夠遍歷結構中的全部元素,若是須要,提供一個高層次的接口讓訪問者對象能夠訪問每個元素,若是須要,能夠設計成一個複合對象或者一個彙集
 
示例代碼:
  1 public class Client {
  2     private static ObjectStructure Objects;
  3     private static Visitor visitor;
  4     public static void main(String[] args) {
  5         //建立一個結構對象
  6         Objects = new ObjectStructure();
  7         //給結構增長一個節點
  8         Objects.add(new NodeA());
  9         //給結構增長一個節點
 10         Objects.add(new NodeB());
 11         //建立一個新訪問者
 12         visitor = new VisitorA();
 13         //讓訪問者訪問結構
 14         Objects.action(visitor);
 15     }
 16 }
 17 //抽象訪問者
 18 interface Visitor{
 19     //對應於nodeA的訪問操做
 20     void visit(NodeA node);
 21     //對應於nodeB的訪問操做
 22     void visit(NodeB node);
 23     
 24 }
 25 //具體訪問者A
 26 class VisitorA implements Visitor{
 27 
 28     @Override
 29     public void visit(NodeA node) {
 30         System.out.println(node.operationA());
 31     }
 32 
 33     @Override
 34     public void visit(NodeB node) {
 35         System.out.println(node.operationB());
 36     }
 37     
 38 }
 39 //具體訪問者B
 40 class VisitorB implements Visitor{
 41 
 42     @Override
 43     public void visit(NodeA node) {
 44         System.out.println(node.operationA());
 45     }
 46 
 47     @Override
 48     public void visit(NodeB node) {
 49         System.out.println(node.operationB());
 50     }
 51     
 52 }
 53 //抽象結點
 54 abstract class Node{
 55     //接受操做
 56     public abstract void accept(Visitor visitor);
 57 }
 58 //具體節點A
 59 class NodeA extends Node{
 60 
 61     @Override
 62     public void accept(Visitor visitor) {
 63         visitor.visit(this);
 64     }
 65     //nodeA的特有商業方法
 66     public String operationA(){
 67         return "Node A is visited";
 68     }
 69 }
 70 //具體節點B
 71 class NodeB extends Node{
 72     @Override
 73     public void accept(Visitor visitor) {
 74         visitor.visit(this);
 75     }
 76     //nodeA的特有商業方法
 77     public String operationB(){
 78         return "Node B is visited";
 79     }
 80 }
 81 //結構對象角色,它持有一個彙集,並向外界提供add()方法做爲對彙集的管理 操做,經過調用這個方法,能夠動態地增長一個新的節點。
 82 class ObjectStructure{
 83     private Vector nodes;
 84     private Node node;
 85     //構造方法
 86     public ObjectStructure(){
 87         nodes = new Vector();
 88     }
 89     //執行訪問操做
 90     public void action(Visitor visitor){
 91         for(Iterator it = nodes.iterator();it.hasNext();){
 92             node = (Node)it.next();
 93             node.accept(visitor);
 94         }
 95     }
 96     
 97     //增長一個新的元素
 98     public void add(Node node){
 99         nodes.add(node);
100     }
101 }
102 //此示意性實現中並無出現一個複雜的具備多個樹枝節點的對象樹結構,可是,在實際系統中訪問者模式一般用來處理複雜的對象樹結構的,並且
103 //訪問者模式能夠用來處理跨越多個等級結構的樹結構問題。這正是訪問者模式的功能強大之處。

 

訪問者模式不該當在什麼狀況下使用?
1.傾斜的可擴展性:訪問者模式應當在被訪問的類結構很是穩定的狀況下使用。換另外一句話,系統不多出現須要加入新節點的狀況。若是出現須要加入新節點的狀況,那時就必須在每個訪問對象里加入一個對應於這個新節點的訪問操做,而這是對一個系統的大規模修改,是違反「開閉」原則 的
    訪問者模式容許在節點中加入新的方法,相應的僅僅須要在一個新的訪問者類中加入此方法,而不須要在每個訪問者類中都加入此方法。
訪問者模式提供了傾斜的可擴展設計,方法集合的擴展性和類集合的不可擴展性。若是系統的數據結構是頻繁變化 的,則不適合使用訪問者模式
 
優勢
1.訪問者模式使得增長新的操做變得容易,若是一個操做依賴於一個複雜的結構對象的話,那麼通常而言,增長新的操做會很複雜。而使用訪問者模式,增長新的操做就意味着增長一個新的訪問者類,很容易
2.訪問者模式將有關的行爲集中到一個訪問者對象中,而不是分散到一個個的節點類中
3.訪問者模式能夠跨過幾個類的等級結構訪問屬於不一樣的等級結構的成員類。迭代子只能訪問屬於同一個類型等級結構的成員對象,而不能訪問屬於不一樣等級結構的對象。訪問者模式能夠作到這一點
4.積累狀態。每個單獨的訪問者對象都集中了相關的行爲,從而也就能夠在訪問地過程當中將執行操做的狀態積累在本身內部,而不是分散到不少的節點對象中。這是有益於系統維護的優勢
缺點:
1.增長新的節點類變得很困難。每增長一個新的節點都意味着要在抽象訪問者角色中增長一個新的抽象操做,並在每個具體訪問者類中增長相應的具體操做。
2.破壞封裝。訪問者模式要求訪問者對象訪問並調用每個節點對象的操做,這隱含了一個對全部節點對象的要求:它們必須暴露一些本身的操做和內部狀態。否則,訪問者的訪問就變得沒有意義。因爲訪問者對象本身會積累訪問操做所須要的狀態,從而使這些狀態再也不存儲在節點對象中,這也是破壞封裝的。
相關文章
相關標籤/搜索