bigtalk.jpg
第28章 男人和女人——訪問者模式
概念
訪問者模式表示一個作用于某對象結(jié)構(gòu)中的各元素的操作。它可以使你在不改變元素類的前提下,定義作用于這些元素的新操作。
即:將類的操作,變?yōu)樘囟▽ο螅煌谠黾有虏僮鞯臅r(shí)候修改類,而是增加新操作,就定義新對象,作為數(shù)據(jù)參數(shù)傳遞給固定類。
場景
數(shù)據(jù)結(jié)構(gòu)固定的情況下(例如人類只有男人和女人),將操作從數(shù)據(jù)結(jié)構(gòu)中分離出來(比如成功、失敗等的反映定義成類對象傳給數(shù)據(jù)實(shí)現(xiàn)不同操作),將數(shù)據(jù)和其操作實(shí)現(xiàn)了解耦,又可以方便地讓操作擴(kuò)展與演化。
其中,用到了雙分派技術(shù),第一次是不同者的分派(不同操作的訪問類對象,傳遞給被操作的固定類對象),將不同的操作定義為訪問者對象傳給正確的被操作對象,第二次是操作中不同動作的分派(不同的固定類對象,會以不同方式使用訪問者類),訪問者對象中對應(yīng)不同的數(shù)據(jù)對象的操作供其調(diào)用。雙分派意味著執(zhí)行的操作取決于請求的種類和接受者的類型。
實(shí)現(xiàn)
-
Visitor: 抽象訪問者類,單獨(dú)抽象出來表示對數(shù)據(jù)類對象的操作,其中會定義與對應(yīng)固定數(shù)據(jù)子類對應(yīng)的操作(如:
VisitA()
,VisitB()
) - ConcreteVisitor1,ConcreteVisitor2: 具體的訪問者子類,每一個子類表示對數(shù)據(jù)類的一種操作算法,每一個子類對象會實(shí)現(xiàn)對應(yīng)數(shù)據(jù)子類的操作。
-
Element: 包含固定子類的抽象數(shù)據(jù)類,定義一個用來接收Visitor為參數(shù)的接口(如:
accept()
),接收的Visitor便是對數(shù)據(jù)的操作。 -
ConcreteElementA,ConcreteElementB: 數(shù)據(jù)子類,實(shí)現(xiàn)
accept()
操作(一般就是調(diào)用Visit的對應(yīng)操作),也包含一些自己的屬性方法。 - ObjectStructure, 對Element對象的枚舉,可以提供一個高層接口允許訪問者訪問它的元素,其中的
accept()
循環(huán)調(diào)用Element的accept()
。 -
Client: 如:創(chuàng)建ObjectStructure列表l,Element子對象e,將所有e加入l,創(chuàng)建Visitor子對象v,調(diào)用
l.accept(v)
以實(shí)現(xiàn)對所有e操作。
實(shí)現(xiàn)類圖:
image.png
總結(jié)起來即:
- 操作抽象類–訪問者類,包含 {A的操作,B的操作} 兩個接口;不同操作定義不同對象類,都繼承這個類形成各自的{A/B}一套操作。
- 元素抽象類–固定類,包含{接受}這一個接口;A類的{接受}調(diào)用訪問者中{A的操作},B類的{接受}調(diào)用訪問者中{B的操作}。
使用類圖:
image.png
雙分派,發(fā)生在 o.Accept(v)
調(diào)用的時(shí)候,假設(shè)o對象對應(yīng)的固定類有A和B,而v對象對應(yīng)了許多不同操作相關(guān)的訪問者類,第一次分派就是將v傳遞給了正確的o(是A或者B),第二次分配就是調(diào)用到正確的v函數(shù)(是A的操作還是B的操作)。
特征
- 數(shù)據(jù)類型是穩(wěn)定的不會變化(比如人只有男人和女人),這樣抽象出來的操作對象里面的對應(yīng)方法也是固定的不會變化,若數(shù)據(jù)變化會很麻煩。
- 支持?jǐn)?shù)據(jù)的操作可變化,變化時(shí)可以定義和修改抽象出來的操作對象而不用改到具體的數(shù)據(jù)對象,體現(xiàn)了開放封閉原則。
舉例
- 操作:失敗(其中有:男人動作,女人動作)、成功(其中有男人動作,女人動作)
- 數(shù)據(jù):男人(其中調(diào)用操作中的“男人動作”)、女人(其中調(diào)用操作中的“女人動作”)
- 使用:將操作傳遞給數(shù)據(jù)完成第一次分派;數(shù)據(jù)中的通用結(jié)構(gòu)accept調(diào)用操作中的針對性動作。