Java 訪問(wèn)者模式

一忧风、概述

將作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作分離出來(lái)封裝成獨(dú)立的類(lèi)布轿,使其在不改變數(shù)據(jù)結(jié)構(gòu)的前提下可以添加作用于這些元素的新的操作甫煞,為數(shù)據(jù)結(jié)構(gòu)中的每個(gè)元素提供多種訪問(wèn)方式掺冠。它將對(duì)數(shù)據(jù)的操作與數(shù)據(jù)結(jié)構(gòu)進(jìn)行分離沉馆,是行為類(lèi)模式中最復(fù)雜的一種模式。

主要角色:

抽象訪問(wèn)者角色:定義一個(gè)訪問(wèn)具體元素的接口德崭,為每個(gè)具體元素類(lèi)對(duì)應(yīng)一個(gè)訪問(wèn)操作 visit() 斥黑,該操作中的參數(shù)類(lèi)型標(biāo)識(shí)了被訪問(wèn)的具體元素。

具體訪問(wèn)者角色:實(shí)現(xiàn)抽象訪問(wèn)者角色中聲明的各個(gè)訪問(wèn)操作眉厨,確定訪問(wèn)者訪問(wèn)一個(gè)元素時(shí)該做什么锌奴。

抽象元素角色:聲明一個(gè)包含接受操作 accept() 的接口,被接受的訪問(wèn)者對(duì)象作為 accept() 方法的參數(shù)憾股。

具體元素角色:實(shí)現(xiàn)抽象元素角色提供的 accept() 操作鹿蜀,其方法體通常都是 visitor.visit(this) 箕慧,另外具體元素中可能還包含本身業(yè)務(wù)邏輯的相關(guān)操作。

對(duì)象結(jié)構(gòu)角色:是一個(gè)包含元素角色的容器茴恰,提供讓訪問(wèn)者對(duì)象遍歷容器中的所有元素的方法销钝,通常由 List、Set琐簇、Map 等聚合類(lèi)實(shí)現(xiàn)蒸健。

二、代碼實(shí)現(xiàn)

舉例:比如我的朋友們來(lái)訪問(wèn)我家婉商,我家有很多的房間似忧,每個(gè)朋友都會(huì)訪問(wèn)我不同的房間,角色分類(lèi)如下:

具體訪問(wèn)者角色:我的朋友們

具體元素角色:房間

對(duì)象結(jié)構(gòu)角色:我家

我家中包含很多房間丈秩,就是對(duì)象結(jié)構(gòu)角色包含元素角色盯捌。接下來(lái)看代碼實(shí)現(xiàn):

抽象訪問(wèn)者角色:朋友

public interface Friend {
    //訪問(wèn)房間A
    void visit(RoomA roomA);
    //訪問(wèn)房間B
    void visit(RoomB roomB);
}

具體訪問(wèn)者角色:張三

public class ZhangSan implements Friend{
    @Override
    public void visit(RoomA roomA) {
        System.out.println("張三訪問(wèn)房間A");
    }

    @Override
    public void visit(RoomB roomB) {
        System.out.println("張三訪問(wèn)房間B");
    }
}

具體訪問(wèn)者角色:李四

public class LiSi implements Friend{

    @Override
    public void visit(RoomA roomA) {
        System.out.println("李四訪問(wèn)房間A");
    }

    @Override
    public void visit(RoomB roomB) {
        System.out.println("李四訪問(wèn)房間B");
    }
}

抽象元素角色:房間

public interface Room {
    //接收訪問(wèn)
    void accept(Friend friend);
}

具體元素角色:房間A

public class RoomA implements Room{
    @Override
    public void accept(Friend friend) {
        friend.visit(this);
        System.out.println("訪問(wèn)了房間A");
    }
}

具體元素角色:房間B

public class RoomB implements Room{
    @Override
    public void accept(Friend friend) {
        friend.visit(this);
        System.out.println("訪問(wèn)了房間B");
    }
}

對(duì)象結(jié)構(gòu)角色:房子

public class Home {
    //房子中包含房間
    private List<Room> list = new ArrayList<>();

    public void addRoom(Room room){
        list.add(room);
    }

    public void action(Friend friend){
        for (Room room:list){
            room.accept(friend);
        }
    }
}

使用:

public static void main(String[] args) {
        //創(chuàng)建房子
        Home home = new Home();
        //添加房間
        home.addRoom(new RoomA());
        home.addRoom(new RoomB());

        //張三
        ZhangSan zhangsan = new ZhangSan();
        //張三訪問(wèn)房間
        home.action(zhangsan);

        //李四
        LiSi lisi = new LiSi();
        home.action(lisi);
    }

輸出:

張三訪問(wèn)房間A
張三訪問(wèn)房間B
李四訪問(wèn)房間A
李四訪問(wèn)房間B

三、總結(jié)

優(yōu)點(diǎn):

  1. 擴(kuò)展性好蘑秽。能夠在不修改對(duì)象結(jié)構(gòu)中的元素的情況下饺著,為對(duì)象結(jié)構(gòu)中的元素添加新的功能。
  2. 復(fù)用性好肠牲∮姿ィ可以通過(guò)訪問(wèn)者來(lái)定義整個(gè)對(duì)象結(jié)構(gòu)通用的功能,從而提高系統(tǒng)的復(fù)用程度缀雳。
  3. 靈活性好渡嚣。訪問(wèn)者模式將數(shù)據(jù)結(jié)構(gòu)與作用于結(jié)構(gòu)上的操作解耦,使得操作集合可相對(duì)自由地演化而不影響系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)肥印。
  4. 符合單一職責(zé)原則识椰。訪問(wèn)者模式把相關(guān)的行為封裝在一起,構(gòu)成一個(gè)訪問(wèn)者深碱,使每一個(gè)訪問(wèn)者的功能都比較單一腹鹉。

缺點(diǎn):

  1. 增加新的元素類(lèi)很困難。在訪問(wèn)者模式中敷硅,每增加一個(gè)新的元素類(lèi)功咒,都要在每一個(gè)具體訪問(wèn)者類(lèi)中增加相應(yīng)的具體操作,這違背了“開(kāi)閉原則”竞膳。
  2. 破壞封裝航瞭。訪問(wèn)者模式中具體元素對(duì)訪問(wèn)者公布細(xì)節(jié)诫硕,這破壞了對(duì)象的封裝性坦辟。
  3. 違反了依賴(lài)倒置原則。訪問(wèn)者模式依賴(lài)了具體類(lèi)章办,而沒(méi)有依賴(lài)抽象類(lèi)锉走。

使用場(chǎng)景:

  1. 對(duì)象結(jié)構(gòu)相對(duì)穩(wěn)定滨彻,但其操作算法經(jīng)常變化的程序。
  2. 對(duì)象結(jié)構(gòu)中的對(duì)象需要提供多種不同且不相關(guān)的操作挪蹭,而且要避免讓這些操作的變化影響對(duì)象的結(jié)構(gòu)亭饵。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市梁厉,隨后出現(xiàn)的幾起案子辜羊,更是在濱河造成了極大的恐慌,老刑警劉巖词顾,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件八秃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡肉盹,警方通過(guò)查閱死者的電腦和手機(jī)昔驱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)上忍,“玉大人骤肛,你說(shuō)我怎么就攤上這事∏侠叮” “怎么了腋颠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)吓笙。 經(jīng)常有香客問(wèn)我秕豫,道長(zhǎng),這世上最難降的妖魔是什么观蓄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任混移,我火速辦了婚禮,結(jié)果婚禮上侮穿,老公的妹妹穿的比我還像新娘歌径。我一直安慰自己,他們只是感情好亲茅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布回铛。 她就那樣靜靜地躺著,像睡著了一般克锣。 火紅的嫁衣襯著肌膚如雪茵肃。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天袭祟,我揣著相機(jī)與錄音验残,去河邊找鬼。 笑死巾乳,一個(gè)胖子當(dāng)著我的面吹牛您没,可吹牛的內(nèi)容都是我干的鸟召。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼氨鹏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欧募!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起仆抵,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤跟继,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后镣丑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體还栓,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年传轰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剩盒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慨蛙,死狀恐怖辽聊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情期贫,我是刑警寧澤跟匆,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站通砍,受9級(jí)特大地震影響玛臂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜封孙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一迹冤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧虎忌,春花似錦泡徙、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挑围,卻和暖如春礁竞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杉辙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工模捂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓枫绅,卻偏偏與公主長(zhǎng)得像泉孩,于是被迫代替她去往敵國(guó)和親硼端。 傳聞我的和親對(duì)象是個(gè)殘疾皇子并淋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一、引子 對(duì)于系統(tǒng)中一個(gè)已經(jīng)完成的類(lèi)層次結(jié)構(gòu)珍昨,我們已經(jīng)給它提供了滿(mǎn)足需求的接口县耽。但是面對(duì)新增加的需求,我們應(yīng)該怎么...
    Java_蘇先生閱讀 156評(píng)論 0 0
  • >《設(shè)計(jì)模式》一書(shū)對(duì)于訪問(wèn)者模式給出的定義為:表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作镣典。它使你可以在不改變各元素的...
    孔祥子看天下閱讀 862評(píng)論 0 0
  • 概述 表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作兔毙。它使你可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新的操作。...
    今晚打肉山閱讀 369評(píng)論 0 0
  • 在閻宏博士的《JAVA與模式》一書(shū)中開(kāi)頭是這樣描述訪問(wèn)者(Visitor)模式的: 訪問(wèn)者模式是對(duì)象的行為模式兄春。訪...
    java雅雅閱讀 167評(píng)論 0 0
  • Java訪問(wèn)者模式 在訪問(wèn)者模式中澎剥,使用訪問(wèn)者類(lèi)來(lái)改變?cè)仡?lèi)的執(zhí)行算法。 通過(guò)這種方式赶舆,元素的執(zhí)行算法可以隨訪問(wèn)者...
    木易林1閱讀 168評(píng)論 0 0