C++實(shí)現(xiàn)訪問(wèn)者模式的基礎(chǔ)介紹
一、訪問(wèn)者模式基礎(chǔ)知識(shí)
1.1 模式動(dòng)機(jī)
對(duì)于系統(tǒng)中的某些對(duì)象中可能存在多種不同類(lèi)型的元素,而且不同的調(diào)用者使用這些元素時(shí)也有所區(qū)別,這些調(diào)用者稱為訪問(wèn)者。
訪問(wèn)者模式(Visitor Pattern):表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中各元素的操作,它使我們可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作。
訪問(wèn)者模式的應(yīng)用場(chǎng)景:
- 訪問(wèn)者模式適用于數(shù)據(jù)結(jié)構(gòu)相對(duì)穩(wěn)定的系統(tǒng)
- 它把數(shù)據(jù)結(jié)構(gòu)和作用于數(shù)據(jù)結(jié)構(gòu)之上的操作之間的耦合解脫開(kāi),使得操作集合可以相對(duì)自由的演化。
- 訪問(wèn)者模式的目的是要把處理從數(shù)據(jù)結(jié)構(gòu)分離出來(lái)。如果這樣的系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),又有已與變化的算法的話,使用訪問(wèn)者模式就是比較合適的,因?yàn)樵L問(wèn)者模式使得算法操作的增加變得更容易。反之亦然。
1.2 訪問(wèn)者模式結(jié)構(gòu)

訪問(wèn)者模式中對(duì)象結(jié)構(gòu)存儲(chǔ)了不同類(lèi)型的元素對(duì)象,以提供不同訪問(wèn)者訪問(wèn)。訪問(wèn)者模式包括兩個(gè)層次結(jié)構(gòu),一個(gè)是訪問(wèn)者層次結(jié)構(gòu),提供了抽象訪問(wèn)者和具體訪問(wèn)者,一個(gè)是元素層次結(jié)構(gòu),提供了抽象元素和具體元素。
相同的訪問(wèn)者可以以不同的方式訪問(wèn)不同的元素,相同的元素可以接受不同訪問(wèn)者以不同的方式訪問(wèn)。
(1)Visitor (抽象訪問(wèn)者)
抽象訪問(wèn)者為對(duì)象結(jié)構(gòu)類(lèi)中每一個(gè)具體元素類(lèi)聲明一個(gè)訪問(wèn)操作。
(2)ConcreteVisitor (具體訪問(wèn)者)
具體訪問(wèn)者實(shí)現(xiàn)了每個(gè)由抽象訪問(wèn)者聲明的操作,每一個(gè)操作用于訪問(wèn)對(duì)象結(jié)構(gòu)中一種元素類(lèi)型的元素。
(3)Element(抽象元素)
抽象元素一般是抽象類(lèi)或接口,定義一個(gè)accept()方法,該方法以一個(gè)抽象訪問(wèn)者作為參數(shù)。
(4)ConcreteElement (具體元素)
具體訪問(wèn)者實(shí)現(xiàn)了accept()方法,在其accept()
(5)ObjectStructure(對(duì)象結(jié)構(gòu))
對(duì)象結(jié)構(gòu)是一個(gè)元素的集合,它用于存放元素對(duì)象,并且提供了遍歷其內(nèi)部元素的方法。
1.3 訪問(wèn)者模式優(yōu)缺點(diǎn)
訪問(wèn)者模式優(yōu)點(diǎn):
- 訪問(wèn)者模式的優(yōu)點(diǎn)就是增加新的操作很容易,因?yàn)樵黾有碌牟僮骶鸵馕吨黾右粋€(gè)新的訪問(wèn)者。訪問(wèn)者模式將有關(guān)的行為集中到一個(gè)訪問(wèn)者對(duì)象中。
模式的缺點(diǎn):
- 使增加新的元素類(lèi)變得困難。在訪問(wèn)者模式中,每增加一個(gè)新的元素都意味著要在抽象訪問(wèn)者角色中增加一個(gè)新的抽象操作,并在每一個(gè)具體訪問(wèn)者中增加相應(yīng)的具體操作,違背“開(kāi)閉原則”的要求。
1.4 訪問(wèn)者模式應(yīng)用
#include <iostream>
#include <vector>
using namespace std;
class ConcreteElementA;
class ConcreteElementB;
/*抽象訪問(wèn)者 聲明了訪問(wèn)元素對(duì)象的方法,通常為每一種類(lèi)型的元素對(duì)象都提供一個(gè)訪問(wèn)方法*/
class Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};
/*具體訪問(wèn)者 用于定義對(duì)不同類(lèi)型元素對(duì)象的操作*/
class ConcreteVisitor1 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA){
// 現(xiàn)在根據(jù)傳進(jìn)來(lái)的pElementA,可以對(duì)ConcreteElementA中的element進(jìn)行操作
}
void VisitConcreteElementB(ConcreteElementB *pElementB){
// 現(xiàn)在根據(jù)傳進(jìn)來(lái)的pElementB,可以對(duì)ConcreteElementB中的element進(jìn)行操作
}
};
/*具體訪問(wèn)者2*/
class ConcreteVisitor2 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA){
}
void VisitConcreteElementB(ConcreteElementB *pElementB){
}
};
/*抽象元素類(lèi) 聲明accept()方法,用于接受訪問(wèn)者的訪問(wèn)*/
class Element
{
public:
virtual void Accept(Visitor *pVisitor) = 0;//accept用于接受訪問(wèn)者的訪問(wèn)
};
/*具體元素類(lèi) 通過(guò)調(diào)用Visitor類(lèi)的visit()方法實(shí)現(xiàn)對(duì)元素的訪問(wèn)*/
class ConcreteElementA : public Element
{
public:
void Accept(Visitor *pVisitor)//通過(guò)調(diào)用visitor對(duì)象的 visit()方法實(shí)現(xiàn)對(duì)元素對(duì)象的訪問(wèn)
{
pVisitor->VisitConcreteElementA(this);
}
};
/*具體元素類(lèi) */
class ConcreteElementB : public Element
{
public:
void Accept(Visitor *pVisitor)
{
pVisitor->VisitConcreteElementB(this);
}
};
// ObjectStructure類(lèi)(對(duì)象結(jié)構(gòu)類(lèi)),能枚舉它的元素,可以提供一個(gè)高層的接口以允許訪問(wèn)者訪問(wèn)它的元素
class ObjectStructure
{
public:
void Attach(Element *pElement){
elements.push_back(pElement);
}
void Detach(Element *pElement)
{
vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
if (it != elements.end())
{
elements.erase(it);
}
}
void Accept(Visitor *pVisitor){
// 為每一個(gè)element設(shè)置visitor,進(jìn)行對(duì)應(yīng)的操作
for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
{
(*it)->Accept(pVisitor);
}
}
int main()
{
//實(shí)例化對(duì)象結(jié)構(gòu),用于存放元素對(duì)象,提供遍歷其內(nèi)部元素的方法
ObjectStructure *pObject = new ObjectStructure;
//實(shí)例化具體元素 并將創(chuàng)建好的元素放入對(duì)象結(jié)構(gòu)中
ConcreteElementA *pElementA = new ConcreteElementA;
ConcreteElementB *pElementB = new ConcreteElementB;
pObject->Attach(pElementA);
pObject->Attach(pElementB);
//實(shí)例化訪問(wèn)者
ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;
//調(diào)用accept方法 來(lái)接受訪問(wèn)者對(duì)象的訪問(wèn)
pObject->Accept(pVisitor1);
pObject->Accept(pVisitor2);
if (pVisitor2) delete pVisitor2;
if (pVisitor1) delete pVisitor1;
if (pElementB) delete pElementB;
if (pElementA) delete pElementA;
if (pObject) delete pObject;
return 0;
}
參考文獻(xiàn):
【1】訪問(wèn)者模式(c++實(shí)現(xiàn)):訪問(wèn)者模式(c++實(shí)現(xiàn))
【2】C++設(shè)計(jì)模式之訪問(wèn)者模式: http://www.fzitv.net/article/55999.htm
到此這篇關(guān)于C++實(shí)現(xiàn)訪問(wèn)者模式的文章就介紹到這了,更多相關(guān)C++訪問(wèn)者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++封裝靜態(tài)鏈接庫(kù)和使用的詳細(xì)步驟
這篇文章主要介紹了C++封裝靜態(tài)鏈接庫(kù)和使用,本文描述了怎么去把一個(gè)C++程序封裝成一個(gè)靜態(tài)庫(kù)并且如何去使用這些靜態(tài)庫(kù),需要的朋友可以參考下2022-08-08
CFileDialog設(shè)置多選的問(wèn)題解決
前幾天同事問(wèn)我在CFileDialog中多選時(shí)按確定按鈕后DoModal函數(shù)的返回值是IDCANCEL的問(wèn)題解決2013-02-02
OPENMP?SECTIONS?CONSTRUCT原理示例解析
這篇文章主要為大家介紹了OPENMP?SECTIONS?CONSTRUCT原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
C++實(shí)現(xiàn)Dijkstra算法的示例代碼
迪杰斯特拉算法(Dijkstra)是由荷蘭計(jì)算機(jī)科學(xué)家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是從一個(gè)頂點(diǎn)到其余各頂點(diǎn)的最短路徑算法。本文將用C++實(shí)現(xiàn)Dijkstra算法,需要的可以參考一下2022-07-07

