訪問者模式 定義 表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。 UML圖 特點 訪問者模式適用於數據結構相對穩定的系統,它把數據和作用於結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化 訪問者模式的目的是要把處理從數據結構分離 ...
訪問者模式
定義
表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
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時,背後多半是個會打扮。