目錄
1、訪問者模式含義
2、訪問者模式的UML圖學習
3、訪問者模式的應用場景
4、訪問者模式的優缺點
5、訪問者模式C++實現的實例
1、訪問者模式含義
????????訪問者模式(Visitor Pattern)是一種行為型設計模式,它允許將一個作用于某對象結構中的各元素的操作分離出來,封裝成獨立的類,使其在不改變數據結構的前提下可以添加作用于這些元素的新的操作,為數據結構中的每個元素提供多種訪問方式。
????????該模式的核心思想是操作分離,通過定義一個外部訪問者類來擴展復雜對象結構的功能,將數據結構與數據操作解耦,使得操作可以獨立于對象的類來定義。
2、訪問者模式的UML圖學習
訪問者模式的UML類圖通常包含以下角色:
(1)抽象訪問者(Visitor):聲明了一個或者多個訪問操作,形成所有的具體元素角色必須實現的接口。
(2)具體訪問者(ConcreteVisitor):實現抽象訪問者角色所聲明的接口,也就是抽象訪問者所聲明的各個訪問操作。
(3)抽象節點(Element):聲明一個接受操作,接受一個訪問者對象作為一個參量。
(4)具體節點(ConcreteNode):實現了抽象節點所規定的接受操作。
(5)結構對象(ObjectStructure):可以遍歷結構中的所有元素;如果需要,提供一個高層次的接口讓訪問者對象可以訪問每一個元素;如果需要,可以設計成一個復合對象或者一個聚集,如列(List)或集合(Set)。
3、訪問者模式的應用場景
(1)數據結構穩定的場景:數據結構(如對象結構)相對穩定,但經常需要對其上的元素執行不同的操作時,訪問者模式非常有用。
(2)需要多種不同操作而不希望修改元素類的場景:如果你有多個不同的操作需要應用到同一組元素上,且不希望在元素類中添加這些操作,訪問者模式可以提供一種解決方案。
(3)需要跨不同類層次結構進行操作的場景:當需要在多個不相關的類層次結構上執行操作時,訪問者模式可以將操作與類層次結構分離。
(4)需要在對象結構中執行復雜計算的場景:訪問者模式可以用于在對象結構中執行復雜的計算或邏輯,而不需要修改元素類本身。
4、訪問者模式的優缺點
(1)優點:
- 符合單一職責原則:訪問者模式將元素操作封裝在訪問者類中,使得元素類專注于其核心職責,而不需要關心如何處理不同的操作。
- 優秀的擴展性:通過添加新的訪問者類,可以很容易地擴展對象結構的功能,而不需要修改元素類。
- 聚合關系:訪問者模式使得元素和訪問者之間形成了一種聚合關系,從而提高了系統的靈活性和可維護性。
- 具體元素變更不頻繁:如果元素類比較穩定,即不易發生變更,那么訪問者模式將非常適用。
(2)缺點
- 增加具體元素和訪問者類的難度:每次在元素結構中增加新的元素類時,都需要修改訪問者類,這違反了開閉原則。
- 破壞封裝:訪問者模式需要訪問元素類的內部數據和方法,這可能會破壞元素的封裝性。
- 具體元素變更困難:如果元素類經常發生變更,那么訪問者模式將變得難以維護,因為每次變更都需要修改訪問者類。
5、訪問者模式C++實現的實例
#include <iostream>
#include <vector>// 元素接口
class Element {
public:virtual void accept(class Visitor* visitor) = 0;virtual ~Element() {}
};// 具體元素A
class ConcreteElementA : public Element {
public:void accept(Visitor* visitor) override {visitor->visitConcreteElementA(this);}void operationA() {std::cout << "ConcreteElementA's operationA" << std::endl;}
};// 具體元素B
class ConcreteElementB : public Element {
public:void accept(Visitor* visitor) override {visitor->visitConcreteElementB(this);}void operationB() {std::cout << "ConcreteElementB's operationB" << std::endl;}
};// 訪問者接口
class Visitor {
public:virtual void visitConcreteElementA(ConcreteElementA* element) = 0;virtual void visitConcreteElementB(ConcreteElementB* element) = 0;virtual ~Visitor() {}
};// 具體訪問者
class ConcreteVisitor : public Visitor {
public:void visitConcreteElementA(ConcreteElementA* element) override {std::cout << "ConcreteVisitor visiting ConcreteElementA" << std::endl;element->operationA();}void visitConcreteElementB(ConcreteElementB* element) override {std::cout << "ConcreteVisitor visiting ConcreteElementB" << std::endl;element->operationB();}
};// 對象結構
class ObjectStructure {
private:std::vector<Element*> elements;
public:void addElement(Element* element) {elements.push_back(element);}void accept(Visitor* visitor) {for (Element* element : elements) {element->accept(visitor);}}
};int main() {ObjectStructure os;os.addElement(new ConcreteElementA());os.addElement(new ConcreteElementB());ConcreteVisitor visitor;os.accept(&visitor);// 清理內存(在實際應用中,應使用智能指針等機制來管理內存)// 這里為了簡單起見,沒有包含清理代碼return 0;
}
在這個實例中,Element
?是元素接口,ConcreteElementA
?和?ConcreteElementB
?是具體元素類。Visitor
?是訪問者接口,ConcreteVisitor
?是具體訪問者類。ObjectStructure
?是對象結構,它包含多個元素,并允許訪問者訪問這些元素。在?main
?函數中,我們創建了一個對象結構,添加了一些元素,并使用訪問者來訪問這些元素。