設計模式GOF23——訪問者模式

訪問者模式(Visitor),是一種行爲性模型,行爲型模式關注的是系統中對象之間的相互交互,解決系統在運行時對象之間的相互通信和協作,進一步明確對象的職責。相比來說,創建型模式關注對象的創建過程,結構型模式關注對象和類的組合關係。

模式的職責

對於存儲在一個集合中的對象,他們可能具有不同的類型(即使有一個公共的接口),對於該集合中的對象,可以接收一類成爲訪問者的對象來訪問,不同的訪問者其訪問方式也有所不同。
表示一個作用於某對象結構中的各元素的操縱它使我們可以在不改變個元素的來的前提下定義作用於這些元素的新操作。

模式的使用場景

XML文檔解析器設計
表一起的設計
複雜集合對象的處理

模式的結構

抽象訪問者:對訪問者的抽象,聲明訪問者可以訪問那些元素。
訪問者:實現抽象訪問者中的訪問方法,它影響到訪問者訪問到一個類後該做什麼,要做什麼。
抽象元素類:對元素類的抽象,聲明接受哪一類訪問者訪問。
元素類:實現對於抽象的實現,一般是定式vistor vistor(this)。
結構對象:一個元素的容器,一般可以包含不同類,不同接口的容器

模式的實現

//元素抽象類
public interface Element {
    //元素接收訪問者訪問的方法
    void accept(Victor vister);
    //元素能執行的方法
    void elementCando();
}
//元素的具體實現
class Element1 implements Element{
    //接收訪問者訪問的方法
    public void accept(Victor vister) {
        vister.visit(this);
    }
    //該元素本身的邏輯和方法(可以有很多)
    public void elementCando() {
        System.out.println("我是元素1,這是我的方法");
    }
}
//元素的具體實現
class Element2 implements Element{
    //接收訪問者訪問的方法
    public void accept(Victor vister) {
        vister.visit(this);
    }
    //該元素本身的邏輯和方法(可以有很多)
    public void elementCando() {
        System.out.println("我是元素2,這是我的方法");
    }
}
//訪問這的抽象類
public interface Victor {
    //對於元素1的訪問
    void visit(Element1 e1);
    //對於元素2的訪問
    void visit(Element2 e2);
}
class VictorImp implements Victor{
    //對於元素1訪問的具體實現
    public void visit(Element1 e1) {
        System.out.println("我在vistit中可以調用元素1啦!那我就直接用");
        e1.elementCando();
    }
    //對於元素2訪問的具體實現
    public void visit(Element2 e2) {
        System.out.println("我在vistit中可以調用元素2啦!那我就直接用");
        //具體調用的方法可以用其他方法實現
        e2.elementCando();
    }

}
class VictorImpement implements Victor{
    //對於元素1訪問的具體實現
    public void visit(Element1 e1) {
        System.out.println("我在vistit中可以調用元素1啦!我先不用");
    }
    //執行元素1的方法的方式
    public void doElement1(Element1 e1){
        e1.elementCando();
    }
    //對於元素2訪問的具體實現
    public void visit(Element2 e2) {
        System.out.println("我在vistit中可以調用元素2啦!我先不用");
        //具體調用的方法可以用其他方法實現
    }
    //執行元素2的方法的方式
    public void doElement2(Element2 e2){
        e2.elementCando();
    }

}
//結構對象,用來管理訪問者和元素類之間的關係
public class ObjectStructure {
    //用來記錄元素的對象
    private List<Element>list = new ArrayList<Element>();
    //登記元素的對象
    public void add(Element e){
        list.add(e);
    }
    //讓已經登記元素接收訪問者的訪問
    public void action(Victor v){
        //可以全部接受,也可以由邏輯判斷選擇性的接受
        for(Element e:list){
            e.accept(v);
        }
    }
}
//客戶端調用
public class Client {

    public static void main(String[] args) {
        //創建結構的對象
        ObjectStructure o = new ObjectStructure();
        //創建元素的對象
        Element1 e1 = new Element1();
        Element2 e2 = new Element2();
        //結構對象中登記元素對象
        o.add(e1);
        o.add(e2);
        //創建訪問者對象
        Victor v1 = new VictorImp();
        Victor v2 = new VictorImpement();
        //在創建結構中讓訪問者可以訪問所有元素
        o.action(v1);
        o.action(v2);
        //訪問者註冊了訪問方法調用分離的調用(其實一般都怎麼做)
        v2.visit(e1);
        v2.visit(e2);
    }

}

模式的優缺點

優點
擴展性好:能夠在不修改對象結構中的元素的情況下,爲對象結構中的元素添加新的功能。
複用性好:可以通過訪問者來定義整的對象結構通用的功能,從而提高複用程度。
分離無關行爲:可以通過訪問者來分離無關的行爲,把相關的行爲封裝在一起,構成一個訪問者,這樣每一個訪問者的功能都比較單一。
缺點
對象結構變化很困難:對象結構一旦發送改變,訪問者的接口和訪問者的實現都要發生相應的改變,代價太高。
破壞封裝:訪問者模式通常要對象接口發放內部數據給訪問者和對象結構類,這破壞了對象的封裝性。

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