訪問者模式
定義
表示一個作用于某物件結構中的各元素的操作,它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作,
UML圖

特點
- 訪問者模式適用于資料結構相對穩定的系統,它把資料和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化
- 訪問者模式的目的是要把處理從資料結構分離出來
- 如果有比較穩定的資料結構,又易于變化的演算法的話,使用訪問者模式就是比較合適的,因為訪問者模式使得演算法操作的增加變得容易
- 訪問者模式的優點就是增加新的操作很容易,因為增加新的操作就意味著增加一個新的訪問者,訪問者模式將有關的行為集中到一個訪問者物件中
- 訪問者的缺點其實也就是使增加新的資料結構變得困難,
舉個栗子
人,分為男人和女人,分別描述他/她成功、失敗、戀愛時的不同原因,,,
UML圖

Talk is cheap, show me the code
(屁話少說,放碼過來)
/**
* 狀態
* Created by callmeDevil on 2019/12/22.
*/
public abstract class Action {
// 得到男人結論或反應
public abstract void getManConclusion(Man concreteElementA);
// 得到女人結論或反應
public abstract void getWomanConclusion(Woman concreteElementB);
}
/**
* 成功
* Created by callmeDevil on 2019/12/22.
*/
public class Success extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s時,背后多半有一個偉大的女人,",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s時,背后多半有一個不成功的男人,",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 失敗
* Created by callmeDevil on 2019/12/22.
*/
public class Failing extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s時,背后多半有一個不偉大的女人,",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s時,背后多半有一個成功的男人,",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 戀愛
* Created by callmeDevil on 2019/12/22.
*/
public class Amativeness extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s時,背后多半是個高富帥,",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s時,背后多半是個會打扮,",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 人
* Created by callmeDevil on 2019/12/22.
*/
public abstract class Person {
// 接受
public abstract void accept(Action visitor);
}
/**
* 男人
* Created by callmeDevil on 2019/12/22.
*/
public class Man extends Person{
@Override
public void accept(Action visitor) {
// 首先在客戶端程式中將具體狀態作為引數傳遞給“男人”類完成了一次分派,然后“男人”類呼叫
// 作為引數的“具體狀態”中的方法“男人反應”,同時將自己(this)作為引數傳遞進去,這便完成
// 了第二次分派,這種技術手段稱為“雙分派”,
visitor.getManConclusion(this);
}
}
/**
* 女人
* Created by callmeDevil on 2019/12/22.
*/
public class Woman extends Person{
@Override
public void accept(Action visitor) {
visitor.getWomanConclusion(this);
}
}
/**
* 物件結構
* Created by callmeDevil on 2019/12/22.
*/
public class ObjectStructure {
private List<Person> elements = new ArrayList<>();
// 增加
public void attach(Person element) {
elements.add(element);
}
// 移除
public void detach(Person element) {
elements.remove(element);
}
// 查看顯示
public void display(Action visitor) {
for (Person element : elements) {
element.accept(visitor);
}
}
}
public class Test {
public static void main(String[] args) {
ObjectStructure obj = new ObjectStructure();
// 物件結構中加入要對比的男人和女人
obj.attach(new Man());
obj.attach(new Woman());
// 成功的反應
Success success = new Success();
obj.display(success);
// 失敗的反應
Failing failing = new Failing();
obj.display(failing);
// 戀愛的反應
Amativeness amativeness = new Amativeness();
obj.display(amativeness);
}
}
運行結果
Man Success時,背后多半有一個偉大的女人,
Woman Success時,背后多半有一個不成功的男人,
Man Failing時,背后多半有一個不偉大的女人,
Woman Failing時,背后多半有一個成功的男人,
Man Amativeness時,背后多半是個高富帥,
Woman Amativeness時,背后多半是個會打扮,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/32505.html
標籤:設計模式
上一篇:Provider模式應用demo
下一篇:大話設計模式筆記(二十六)の總結
