訪問者模式

1 測評系統(tǒng)需求

某餐廳推出了一款飲料位谋,想讓品嘗著對其評價成功或失敗。品嘗著可以是男人遥椿、女人基矮,評價可以是成功或失敗。傳統(tǒng)方案是寫一個Person類冠场,然后讓Man和Woman類繼承Person并實現(xiàn)評價功能家浇。傳統(tǒng)方案擴展性不好,如果要增加新的人員類型或評價結(jié)果碴裙,需要修改Person及其子類钢悲,違反開閉原則。而訪問者模式可以很好地解決這個問題舔株。

2 訪問者模式介紹

訪問者模式封裝了一些作用于某種數(shù)據(jù)結(jié)構(gòu)的各元素的操作莺琳,它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作,這種設計模式將數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)操作分離载慈,解決數(shù)據(jù)結(jié)構(gòu)和操作耦合性問題惭等。訪問者模式的基本工作原理是:在被訪問的類里面加一個對外提供接待訪問者的接口。
角色分析:
1)Visitor:抽象訪問者办铡,為該對象結(jié)構(gòu)中的ConcreteElement的每一個類聲明一個visit操作辞做。
2)ConcreteVisitor:具體的訪問者琳要,實現(xiàn)Visitor聲明的操作,是每個操作到的具體實現(xiàn)秤茅。
3)ObjectStructure:對象結(jié)構(gòu)稚补,它能枚舉具體的元素,可以提供一個高層的接口嫂伞,來允許訪問者訪問元素孔厉。
4)Element:元素的抽象類,定義一個accept方法帖努,接收一個訪問者對象撰豺。
5)ConcreteElement:元素的具體實現(xiàn),實現(xiàn)了accept方法拼余。


訪問者模式的類圖

3 用訪問者模式實現(xiàn)評分需求

首先有抽象的訪問者Action:

public abstract class Action {
    abstract void getManResult(Person man);

    abstract void getWomanResult(Person woman);
}

訪問者的具體實現(xiàn)Success污桦、Fail:

public class Success extends Action {
    @Override
    void getManResult(Person man) {
        System.out.println("男人給的評價是:成功");
    }

    @Override
    void getWomanResult(Person woman) {
        System.out.println("女人給的評價是:成功");
    }
}
public class Fail extends Action {
    @Override
    void getManResult(Person man) {
        System.out.println("男人給的評價是:失敗");
    }

    @Override
    void getWomanResult(Person woman) {
        System.out.println("女人給的評價是:失敗");
    }
}

元素的抽象類Person:

public abstract class Person {
    abstract void accept(Action action);
}

具體的元素實現(xiàn)類Man、Woman匙监,需要注意的是:這里使用了雙分派的方式凡橱,首先在客戶端程序中,將具體的狀態(tài)作為參數(shù)傳遞到Man或Woman中(第一次分派)亭姥,然后在Man或Woman類中調(diào)用了作為參數(shù)的"具體方法"中的getWomanResult稼钩,同時將自己(即this)作為參數(shù)傳入(第二次分派)。

public class Man extends Person {
    @Override
    void accept(Action action) {
        action.getManResult(this);
    }
}
public class Woman extends Person {
    @Override
    void accept(Action action) {
        action.getWomanResult(this);
    }
}

ObjectStructure類:

public class ObjectStructure {
    // 維護一個集合
    private List<Person> persons = new LinkedList<>();

    public void attach(Person person) {
        persons.add(person);
    }

    public void detach(Person person) {
        persons.remove(person);
    }

    // 顯示測評結(jié)果
    public void display(Action action) {
        for (Person person : persons) {
            person.accept(action);
        }
    }
}

客戶端調(diào)用:

public class Client {
    public static void main(String[] args) {
        // 創(chuàng)建ObjectStructure對象
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.attach(new Man());
        objectStructure.attach(new Woman());
        objectStructure.attach(new Man());

        // 成功的評價
        Success success = new Success();
        objectStructure.display(success);

        System.out.println("====================");
        // 失敗的評價
        Fail fail = new Fail();
        objectStructure.display(fail);
    }
}

輸出結(jié)果:

男人給的評價是:成功
女人給的評價是:成功
男人給的評價是:成功
====================
男人給的評價是:失敗
女人給的評價是:失敗
男人給的評價是:失敗
評價需求的類圖

4 訪問者模式的優(yōu)缺點

優(yōu)點:
1)訪問者模式符合單一職責原則达罗,可以讓程序具有優(yōu)秀的擴展性和靈活性坝撑。
2)訪問者模式可以對功能進行統(tǒng)一,可以做報表粮揉、UI巡李、攔截器與過濾器,適用于數(shù)據(jù)結(jié)構(gòu)穩(wěn)定地系統(tǒng)扶认。
缺點:
1)對具體元素訪問者公布細節(jié)侨拦,也就是說訪問者關注了其他類的內(nèi)部細節(jié),這是迪米特法則所不建議的辐宾,這樣會造成具體元素的變更比較困難狱从。
2)違背了依賴倒轉(zhuǎn)原則,訪問者依賴的是具體元素叠纹,而不是抽象類矫夯。
因此,如果一個系統(tǒng)具有較穩(wěn)定地數(shù)據(jù)結(jié)構(gòu)吊洼,又有經(jīng)常變化的功能需求训貌,那么訪問者模式是比較合適的。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市递沪,隨后出現(xiàn)的幾起案子豺鼻,更是在濱河造成了極大的恐慌,老刑警劉巖款慨,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒飒,死亡現(xiàn)場離奇詭異,居然都是意外死亡檩奠,警方通過查閱死者的電腦和手機桩了,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埠戳,“玉大人井誉,你說我怎么就攤上這事≌福” “怎么了颗圣?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屁使。 經(jīng)常有香客問我在岂,道長,這世上最難降的妖魔是什么蛮寂? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任蔽午,我火速辦了婚禮,結(jié)果婚禮上酬蹋,老公的妹妹穿的比我還像新娘及老。我一直安慰自己,他們只是感情好除嘹,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布写半。 她就那樣靜靜地躺著岸蜗,像睡著了一般尉咕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上璃岳,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天年缎,我揣著相機與錄音,去河邊找鬼铃慷。 笑死单芜,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的犁柜。 我是一名探鬼主播洲鸠,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扒腕?” 一聲冷哼從身側(cè)響起绢淀,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘾腰,沒想到半個月后皆的,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蹋盆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年费薄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栖雾。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡楞抡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岩灭,到底是詐尸還是另有隱情拌倍,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布噪径,位于F島的核電站柱恤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏找爱。R本人自食惡果不足惜梗顺,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望车摄。 院中可真熱鬧寺谤,春花似錦、人聲如沸吮播。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽意狠。三九已至粟关,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間环戈,已是汗流浹背闷板。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留院塞,地道東北人遮晚。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像拦止,于是被迫代替她去往敵國和親县遣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355