寫文章的初心主要是用來幫助自己快速的回憶這個模式該怎么用,主要是下面的UML圖可以起到大作用,在你學習過一遍以后可能會遺忘,忘記了不要緊,只要看一眼UML圖就能想起來了。同時也請大家多多指教。
訪問者模式(Visitor)
對象行為型模式。
目錄
一、概述
1.1、直觀的理解:
1.2、主要角色:
1.3、描述上述對象之間關系的UML圖:
1.4、適用場景:
二、代碼舉例
2.1、對象之間的關系用UML圖描述如下:
2.2、Java代碼如下:
一、概述
1、表示一個作用于某對象結構中的各個元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作;
2、這算法應當是針對這數據結構里每一個對象建對應的處理,也就是算法對象里有一整個操作集合,使得每一個對象都可以根據不同的具體算法都同一時間段內單獨的操作一下。而針對不同的時間段,又可以新建不同的算法類,同樣算法類里也應該有在同一時間段里對那些數據結構類群里的所有對象的操作。
1.1、直觀的理解:
假設有3個元素,且對這些元素有兩種操作需要實現,使用訪問者模式我們邏輯上的思考應該是:
但在代碼實現上,我們還需要再加一個枚舉元素的類,他存儲了所有相關的元素,并且可以枚舉它們,方便訪問者操作那些元素。
就拿訪問者A訪問元素1、2、3為例,活動圖如下:
1.2、主要角色:
- 訪問者:訪問者的抽象類或接口 + 訪問者類,操作元素的類
- 元素:元素的抽象類或接口 + 元素類,被操作的對象
- 枚舉元素類的類(ObjectStructure對象結構):保存著元素類的集合,并且可以遍歷已保存的元素方便訪問者訪問
1.3、描述上述對象之間關系的UML圖:
1.4、適用場景:
- 一個對象結構包含很多類對象,它們有著不同的接口,而你想對這些對象實施一些依賴于其具體類的操作
- 需要對一個對象結構中的對象進行很多不太并且不相關的操作,而你想要避免讓這些操作“污染”這些對象的類
- 適合于數據結構相對穩定的系統。它把數據結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化
二、代碼舉例
假設有元素A和B,在它們之上有兩類操作,那么設計出訪問者1和2。這個例子比較簡單,就不再詳細分析了。但你可以把本例當做一個模板,然后靈活使用:
2.1、對象之間的關系用UML圖描述如下:
2.2、Java代碼如下:
訪問者的抽象類:
abstract class Visitor {public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
元素的抽象類:
abstract class Element {public abstract void accept(Visitor visitor);
}
元素類A:
public class ConcreteElementA extends Element{@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementA(this);}//其他操作
}
元素類B:
public class ConcreteElementB extends Element{@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementB(this);}//其他操作
}
訪問者1:
public class ConcreteVisitor1 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "訪問");}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "訪問");}
}
訪問者2:
public class ConcreteVisitor2 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "訪問");}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + "被" + this.getClass().getSimpleName() + "訪問");}
}
枚舉元素類的類:
public class ObjectStructure {private List<Element> elements = new ArrayList<>();public void attach(Element element) {elements.add(element);}public void detach(Element element) {elements.remove(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}
主程序(發起請求的類):
public class Main {public static void main(String[] args) {ObjectStructure objectStructure = new ObjectStructure();objectStructure.attach(new ConcreteElementA());objectStructure.attach(new ConcreteElementB());objectStructure.accept(new ConcreteVisitor1());objectStructure.accept(new ConcreteVisitor2());}
}
這里就不再舉例了,可以把上面的Java例子復制到你本地,運行main函數試一下加深理解。這些代碼都是我自己學習的時候根據一些教材手敲的,不存在bug可以直接運行。
如果覺得本文還不錯,就請點個贊給作者一點鼓勵吧!如果有建議,也請評論指教和討論!