博客 / 詳情

返回

訪問者模式

在類的內部結構不變的情況下,不同的訪問者訪問這個對象,都會呈現出不同的效果。

訪問者模式有以下角色

  • 元素類:是一個抽象類或者接口,裏面會定義一個接收(accept)訪問者的抽象方法,使得每一個元素能被訪問者訪問。
  • 具體元素:繼承或實現元素類,實現接收方法。
  • 訪問者:一般是一個抽象類,裏面涵括了可以訪問每個具體元素的方法,使得訪問者可以訪問每個具體元素(一般有幾個具體元素就會有幾個這個樣的方法,這些方法的方法名相同參數不同,參數都是具體元素,所以一般來説具體元素的種類應該是比較固定的)。
  • 具體訪問者:訪問者的具體實現

例如我們定義景區是一個元素類,西湖、長城是一個具體的元素類,遊客就是訪問者的抽象,那麼遊客A、遊客B就是具體的訪問者。

景區類中有一個接收方法參數是遊客類型,由於多態特性所以我們可以傳入遊客A、遊客B等子類。

遊客類中會有多個訪問方法,它們的方法名相同,參數不同,分別為西湖、長城等具體元素類

具體景區-西湖會實現父類中的接收抽象方法,然後方法中調用傳入的遊客對象的訪問方法,參數設為this也就是西湖類的對象,這就相當於調用了遊客類中的參數為西湖的訪問方法。

具體類圖如下

下面使用一個類似的樣例,國家領導人進行國際訪問來進行代碼實現

元素類 - 國家

public abstract class Country {
    private String capital;

    public Country(String capital) {
        this.capital = capital;
    }

    public String getCapital() {
        return capital;
    }

    abstract void accept(NationalLeader leader);
}

具體元素類 - 美國、日本

public class America extends Country {

    public America(String capital) {
        super(capital);
    }

    @Override
    public void accept(NationalLeader leader) {
        leader.visit(this);
    }

}
public class Japan extends Country {

    public Japan(String capital) {
        super(capital);
    }

    @Override
    public void accept(NationalLeader leader) {
        leader.visit(this);
    }
}

訪問者 - 國家領導人

public interface NationalLeader {
    void visit(America america);
    void visit(Japan japan);
    //這裏面還可以訪問 中國、巴西、法國、英國.....被訪問的通常是固定不變的,而訪問者可以是任何人,相對來説更加靈活
}

具體訪問者 - 普京

public class Putin implements NationalLeader{
    @Override
    public void visit(America america) {
        System.out.println("普京抵達美國首都"+america.getCapital());
    }

    @Override
    public void visit(Japan japan) {
        System.out.println("普京抵達日本首都"+japan.getCapital());
    }
}

測試

public class VisitorTest {
    @Test
    public void test(){
        Country america = new America("華盛頓");
        america.accept(new Putin());
        Country japan = new Japan("東京");
        japan.accept(new Putin());
    }
}

=====結果=====
普京抵達美國首都華盛頓
普京抵達日本首都東京

優點:

  1. 使得數據結構(元素類)和作用於結構上的操作(訪問者)解耦,使得操作集合可以獨立變化。
  2. 便於靈活添加操作(訪問者)。
  3. 將對各個元素的一組操作集中在一個訪問者類當中。
  4. 可以跨越類層次結構,訪問不同層次的元素類,做出相應的操作。

缺點:

  1. 增加新的元素會非常困難。
  2. 實現起來比較複雜,會增加系統的複雜性。
  3. 破壞封裝,如果將訪問行為放在各個元素中,則可以不暴露元素的內部結構和狀態,但使用訪問者模式的時候,為了讓訪問者能獲取到所關心的信息,元素類不得不暴露出一些內部的狀態和結構,就像收入和支出類必須提供訪問金額和單子的項目的方法一樣。

適用性:

  1. 數據結構穩定,作用於數據結構的操作經常變化的時候。
  2. 當一個數據結構中,一些元素類需要負責與其不相關的操作的時候,為了將這些操作分離出去,以減少這些元素類的職責時,可以使用訪問者模式。
  3. 有時在對數據結構上的元素進行操作的時候,需要區分具體的類型,這時使用訪問者模式可以針對不同的類型,在訪問者類中定義不同的操作,從而去除掉類型判斷。
user avatar faurewu 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.