訪問者模式

訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操作。一旦這些操作需要修改的話,接收這個操作的數據結構則可以保持不變。

訪問者模式的組成結構:

  1) 訪問者角色(Visitor):爲該對象結構中具體元素角色聲明一個訪問操作接口。該操作接口的名字和參數標識了發送訪問請求給具體訪問者的具體元素角色。這樣訪問者就可以通過該元素角色的特定接口直接訪問它。

  2) 具體訪問者角色(Concrete Visitor):實現每個由訪問者角色(Visitor)聲明的操作。

  3) 元素角色(Element):定義一個Accept操作,它以一個訪問者爲參數。

  4) 具體元素角色(Concrete Element):實現由元素角色提供的Accept操作。

  5) 對象結構角色(Object Structure):這是使用訪問者模式必備的角色。它要具備以下特徵:能枚舉它的元素;可以提供一個高層的接口以允許該訪問者訪問它的元素;可以是一個複合(組合模式)或是一個集合,如一個列表或一個無序集合。

如何讓訪問者模式跑起來?

首先在原有的類層次結構中添加accept方法,然後將這個類層次中的類放到一個對象結構中去,這樣再創建訪問者角色...

public interface Node {
    /**
     * 接收操作
     */
    public void accept(Visitor visitor);
}

 

public class NodeA implements Node {
    /**
     * 接收操作
     */
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
    /**
     * NodeA特有的商業方法,visitor就是對其進行封裝
     */
    public void operationA() {
        System.out.println("NodeA operation");
    }
}

 

public class NodeB implements Node {
    /**
     * 接收操作
     */
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
    /**
     * NodeB特有的商業方法,visitor就是對其進行封裝
     */
    public void operationB() {
        System.out.println("NodeB operation");
    }
}

 

public interface Visitor {
    /**
     * 對應於NodeA的訪問操作
     */
    public void visitor(NodeA node);
    /**
     * 對應於NodeB的訪問操作
     */
    public void visitor(NodeB node);
}

 

public class VisitorA implements Visitor {
    /**
     * 對應於NodeA的訪問操作
     */
    public void visitor(NodeA node) {
        node.operationA();
    }
    /**
     * 對應於NodeB的訪問操作
     */
    public void visitor(NodeB node) {
        node.operationB();
    }
}

 

public class VisitorB implements Visitor {
    /**
     * 對應於NodeA的訪問操作
     */
    public void visitor(NodeA node) {
        node.operationA();
    }
    /**
     * 對應於NodeB的訪問操作
     */
    public void visitor(NodeB node) {
        node.operationB();
    }
}

 

/**
 * 結構對象
 */
public class ObjectStructure {

    private Vector<Node> nodes = new Vector<Node>();
    private Node node;

    /**
     * 執行訪問操作
     */
    public void action(Visitor visitor) {
        for (Node node : nodes) {
            node.accept(visitor);
        }
    }

    /**
     * 增加一個新的元素
     */
    public void add(Node node) {
        nodes.addElement(node);
    }
}

 

public class Client {

    public static void main(String[] args) {
        //創建一個結構對象
        ObjectStructure objectStructure = new ObjectStructure();
        //給結構增加一個節點
        objectStructure.add(new NodeA());
        //給結構增加一個節點
        objectStructure.add(new NodeB());
        //創建一個新訪問者
        Visitor visitor = new VisitorA();
        //讓訪問者訪問結構
        objectStructure.action(visitor);
    }
}

 雙重分派

首先在客戶程序中將具體訪問者模式作爲參數傳遞給具體元素角色,這便完成了一次分派。

進入具體元素角色後,具體元素角色調用作爲參數的具體訪問者模式中的visitor方法,同時將自己(this)作爲參數傳遞進去。具體訪問者模式再根據參數的不同來選擇方法來執行,這便完成了第二次分派。

 

《設計模式》一書中給出了訪問者模式適用的情況:

  1) 一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。

  2) 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor使得你可以將相關的操作集中起來定義在一個類中。

  3) 當該對象結構被很多應用共享時,用Visitor模式讓每個應用僅包含需要用到的操作。

  4) 定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章