設(shè)計(jì)模式(二十四) 訪問(wèn)者模式

訪問(wèn)者模式提供了一種方法,將算法和數(shù)據(jù)結(jié)構(gòu)分離逾苫。假設(shè)我們需要對(duì)一個(gè)數(shù)據(jù)結(jié)構(gòu)進(jìn)行不同的操作卿城,就可以考慮使用訪問(wèn)者模式。訪問(wèn)者模式的要點(diǎn)在于铅搓,需要一個(gè)訪問(wèn)者接口瑟押,提供了一些重載方法來(lái)訪問(wèn)具體對(duì)象。對(duì)于每個(gè)具體對(duì)象星掰,又提供了一個(gè)accept方法來(lái)回調(diào)訪問(wèn)者多望。

首先來(lái)看看訪問(wèn)者嫩舟。

public interface Visitor {
    void visit(House house);

    void visit(Kitchen kitchen);

    void visit(LivingRoom livingRoom);

    void visit(BedRoom bedRoom);
}

class HouseVisitor implements Visitor {
    public void visit(House house) {
        System.out.println("訪問(wèn)了房子");
    }

    public void visit(BedRoom bedRoom) {
        System.out.println("訪問(wèn)了臥室");
    }

    public void visit(LivingRoom livingRoom) {
        System.out.println("訪問(wèn)了客廳");
    }

    public void visit(Kitchen kitchen) {
        System.out.println("訪問(wèn)了廚房");
    }
}

然后是要訪問(wèn)的對(duì)象,這里是一間屋子怀偷。

public class House {
    private LivingRoom livingRoom;
    private Kitchen kitchen;
    private BedRoom bedRoom;

    public House() {
        livingRoom = new LivingRoom();
        kitchen = new Kitchen();
        bedRoom = new BedRoom();
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
        livingRoom.accept(visitor);
        bedRoom.accept(visitor);
        kitchen.accept(visitor);
    }
}

class LivingRoom {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Kitchen {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class BedRoom {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

然后客戶端就可以簡(jiǎn)單的訪問(wèn)屋子了家厌。

    public void run() {
        Visitor visitor = new HouseVisitor();
        House house = new House();
        visitor.visit(house);
    }

這就是訪問(wèn)者模式了∽倒ぃ可能會(huì)同學(xué)會(huì)有疑問(wèn)饭于,為什么我要這么寫?如果讓屋子對(duì)象層次全部都實(shí)現(xiàn)Visitor接口维蒙,然后客戶端直接調(diào)用這些visit方法不是也可以嗎掰吕?一開始我也有這個(gè)疑問(wèn),后來(lái)看了知乎輪子哥的一篇文章ParserGen生成預(yù)定義好的各種visitor颅痊,感覺(jué)茅塞頓開殖熟。

其實(shí)Visitor模式講的就是在不需要擴(kuò)充新的子類的時(shí)候,如何添加新的虛函數(shù)而不需要修改原有代碼斑响。當(dāng)然虛函數(shù)也有它的好處菱属,就是添加新的子類的時(shí)候不需要修改原有代碼。所以看你的業(yè)務(wù)邏輯恋捆,到底是添加新子類多照皆,還是添加新虛函數(shù)多,從而選擇要不要把程序?qū)懗苫赩isitor模式的樣子沸停。

對(duì)于編譯器來(lái)說(shuō),整個(gè)處理流程那么復(fù)雜昭卓,所以等于需要經(jīng)常添加虛函數(shù)愤钾,因此就都把本來(lái)是虛函數(shù)的東西改成了各種Visitor。這個(gè)時(shí)候候醒,如果你修改了語(yǔ)法能颁,那么每一個(gè)Visitor都會(huì)曝出語(yǔ)法錯(cuò)誤,所以這等于變相通知你所有需要修改的東西在哪里——如果你能堅(jiān)持不因?yàn)橥祽卸褂胐ynamic_cast的話倒淫。

所謂設(shè)計(jì)模式伙菊,都需要在特定的環(huán)境中才有用。所以現(xiàn)在我們已經(jīng)了解了什么情況下應(yīng)該使用訪問(wèn)者模式敌土。假如接口中的方法固定镜硕,但是需要添加新的實(shí)現(xiàn)類,那么就使用普通的繼承方式返干。如果接口方法經(jīng)常變動(dòng)兴枯,就可以把接口改寫為訪問(wèn)者。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末矩欠,一起剝皮案震驚了整個(gè)濱河市财剖,隨后出現(xiàn)的幾起案子悠夯,更是在濱河造成了極大的恐慌,老刑警劉巖躺坟,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沦补,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咪橙,警方通過(guò)查閱死者的電腦和手機(jī)夕膀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匣摘,“玉大人店诗,你說(shuō)我怎么就攤上這事∫舭瘢” “怎么了庞瘸?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)赠叼。 經(jīng)常有香客問(wèn)我擦囊,道長(zhǎng),這世上最難降的妖魔是什么嘴办? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任瞬场,我火速辦了婚禮,結(jié)果婚禮上涧郊,老公的妹妹穿的比我還像新娘贯被。我一直安慰自己,他們只是感情好妆艘,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布彤灶。 她就那樣靜靜地躺著,像睡著了一般批旺。 火紅的嫁衣襯著肌膚如雪幌陕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天汽煮,我揣著相機(jī)與錄音搏熄,去河邊找鬼。 笑死暇赤,一個(gè)胖子當(dāng)著我的面吹牛心例,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翎卓,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼契邀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了失暴?” 一聲冷哼從身側(cè)響起坯门,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤微饥,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后古戴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欠橘,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年现恼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肃续。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叉袍,死狀恐怖始锚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喳逛,我是刑警寧澤瞧捌,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站润文,受9級(jí)特大地震影響姐呐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜典蝌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一曙砂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骏掀,春花似錦鸠澈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至侧纯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間甲脏,已是汗流浹背眶熬。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留块请,地道東北人娜氏。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像墩新,于是被迫代替她去往敵國(guó)和親贸弥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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

  • 1 場(chǎng)景問(wèn)題# 1.1 擴(kuò)展客戶管理的功能## 考慮這樣一個(gè)應(yīng)用:擴(kuò)展客戶管理的功能海渊。 既然是擴(kuò)展功能绵疲,那么肯定是...
    七寸知架構(gòu)閱讀 2,896評(píng)論 1 58
  • 設(shè)計(jì)模式基本原則 開放-封閉原則(OCP)哲鸳,是說(shuō)軟件實(shí)體(類、模塊盔憨、函數(shù)等等)應(yīng)該可以拓展徙菠,但是不可修改。開-閉原...
    西山薄涼閱讀 3,753評(píng)論 3 13
  • 設(shè)計(jì)模式匯總 一郁岩、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用婿奔、多...
    MinoyJet閱讀 3,906評(píng)論 1 15
  • Iterator模式 (迭代器) 一個(gè)一個(gè)遍歷 一個(gè)集合類可以遵守 Iterator 協(xié)議,并實(shí)現(xiàn)一個(gè) Itera...
    SSBun閱讀 1,830評(píng)論 0 15
  • 本文是《設(shè)計(jì)模式——可復(fù)用面對(duì)對(duì)象軟件的基礎(chǔ)》的筆記问慎。 面對(duì)對(duì)象設(shè)計(jì)的幾個(gè)原則:1.針對(duì)接口編程萍摊,而不是針對(duì)實(shí)現(xiàn)編...
    Lension閱讀 1,167評(píng)論 0 0