C++設計形式之拜訪者形式。本站提示廣大學習愛好者:(C++設計形式之拜訪者形式)文章只能為提供參考,不一定能成為您想要的結果。以下是C++設計形式之拜訪者形式正文
媒介
這是23+1(簡略工場形式)當中的最初一個了——拜訪者形式。拜訪者形式也是一個比擬費事的設計形式。我也沒有實戰經歷,關於拜訪者形式的懂得完整來自GOF的《設計形式:可復用面向對象軟件的基本》,而這篇文章就是依據對這本書的懂得而寫出來的。在讀《設計形式:可復用面向對象軟件的基本》的時刻,讓我想起本身做過的一個項目,該項目固然沒有應用拜訪者形式,然則,明天懂得了該形式,假如應用該形式對之前做過的項目停止重構,將是一個不錯的設法主意。
拜訪者形式
在GOF的《設計形式:可復用面向對象軟件的基本》一書中對拜訪者形式是如許說的:表現一個感化於某對象構造中的各元素的操作。它使你可以在不轉變各元素的類的條件下界說感化於這些元素的新操作。拜訪者形式把數據構造和感化於構造上的操作之間的耦合擺脫開,使得操作聚集可以絕對自在地演變。該形式的目標是要把處置從數據構造分別出來。拜訪者形式讓增長新的操作很輕易,由於增長新的操作就意味著增長一個新的拜訪者。拜訪者形式將有關的行動集中到一個拜訪者對象中。如今再來講說我之前閱歷過的誰人項目。
是基於Windows Shell開辟的一個項目,在一個容器中存儲了許多的Shell Items,同時界說了對Items的操作,因為項目一向都在停止前期擴大,對Items的操作在前期都須要停止擴大的;而如今的做法是,界說一個操作類,該操作類中界說了一個聚集,該聚集寄存Items,在該操作類中擴大對應的操作辦法。如今想一想假如應用拜訪者形式也是可以的,因為Items聚集是固定的,當須要擴大聚集的操作時,只須要添加對應的拜訪者便可。
UML類圖
Visitor(拜訪者):為該對象構造中ConcreteElement的每個類聲明一個Visit操作。該操作的名字和特點標識了發送Visit要求給該拜訪者的誰人類。這使得拜訪者可以肯定正被拜訪元素的詳細的類。如許拜訪者便可以經由過程該元素的特定接口直接拜訪它。
ConcreteVisitor(詳細拜訪者):完成每一個由Visitor聲明的操作。每一個操作完成本算法的一部門,而該算法片斷乃是對應於構造中對象的類。ConcreteVisitor為該算法供給了高低文並存儲它的部分狀況。這一狀況經常在遍歷該構造的進程中積累成果。
Element(元素):界說一個Accept操作,它以一個拜訪者為參數。
ConcreteElement(詳細元素):完成Accept操作,該操作以一個拜訪者為參數。
ObjectStructure(對象構造):可以或許列舉它的元素,同時供給一個高層的接口以許可該拜訪者拜訪它的元素。
應用場所
1.一個對象構造包括許多類對象,它們有分歧的接口,而你想對這些對象實行一些依附於其詳細類的操作;
2.須要對一個對象構造中的對象停止許多分歧的而且不相干的操作,而你想防止讓這些操作“淨化”這些對象的類。Visitor使得你可以將相干的操作集中起來界說在一個類中;
3.當該對象構造被許多運用同享時,用Visitor形式讓每一個運用僅包括須要用到的操作;
4.界說對象構造的類很少轉變,但常常須要在此構造上界說新的操作。轉變對象構造類須要重界說對一切拜訪者的接口,這能夠須要很年夜的價值。假如對象構造類常常轉變,那末能夠照樣在這些類中界說這些操作較好。
代碼完成
#include <iostream>
#include <vector>
using namespace std;
class ConcreteElementA;
class ConcreteElementB;
class Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};
class ConcreteVisitor1 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA);
void VisitConcreteElementB(ConcreteElementB *pElementB);
};
void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
{
// 如今依據傳出去的pElementA,可以對ConcreteElementA中的element停止操作
}
void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{
// 如今依據傳出去的pElementB,可以對ConcreteElementB中的element停止操作
}
class ConcreteVisitor2 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA);
void VisitConcreteElementB(ConcreteElementB *pElementB);
};
void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
{
// ...
}
void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
{
// ...
}
// Element object
class Element
{
public:
virtual void Accept(Visitor *pVisitor) = 0;
};
class ConcreteElementA : public Element
{
public:
void Accept(Visitor *pVisitor);
};
void ConcreteElementA::Accept(Visitor *pVisitor)
{
pVisitor->VisitConcreteElementA(this);
}
class ConcreteElementB : public Element
{
public:
void Accept(Visitor *pVisitor);
};
void ConcreteElementB::Accept(Visitor *pVisitor)
{
pVisitor->VisitConcreteElementB(this);
}
// ObjectStructure類,能列舉它的元素,可以供給一個高層的接口以許可拜訪者拜訪它的元素
class ObjectStructure
{
public:
void Attach(Element *pElement);
void Detach(Element *pElement);
void Accept(Visitor *pVisitor);
private:
vector<Element *> elements;
};
void ObjectStructure::Attach(Element *pElement)
{
elements.push_back(pElement);
}
void ObjectStructure::Detach(Element *pElement)
{
vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
if (it != elements.end())
{
elements.erase(it);
}
}
void ObjectStructure::Accept(Visitor *pVisitor)
{
// 為每個element設置visitor,停止對應的操作
for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
{
(*it)->Accept(pVisitor);
}
}
int main()
{
ObjectStructure *pObject = new ObjectStructure;
ConcreteElementA *pElementA = new ConcreteElementA;
ConcreteElementB *pElementB = new ConcreteElementB;
pObject->Attach(pElementA);
pObject->Attach(pElementB);
ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;
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;
}
總結
拜訪者形式的根本思惟以下:起首具有一個由很多對象組成的對象構造,就是下面代碼中的ObjectStructure,這些對象的類都具有一個Accept辦法用來接收拜訪者對象;拜訪者是一個接口,它具有一個Visit辦法,這個辦法對拜訪到的對象構造中分歧類型的元素做出分歧的操作;在對象構造的一次拜訪進程中,我們遍歷全部對象構造,對每個元素都實行Accept辦法,在每個元素的Accept辦法中回調拜訪者的Visit辦法,從而使拜訪者得以處置對象構造的每個元素。我們便可以針對對象構造設計分歧的拜訪者類來完成分歧的操作。
設計形式中常常說的一句話是:發明變更並封裝之。能否采取拜訪者形式,就要看“變更”是甚麼。拜訪者形式中,“變更”是詳細拜訪者,其次是對象構造;然則,假如詳細元素也會產生轉變,就切切不克不及應用拜訪者形式,由於如許“牽一發而動全身”,前期的保護性就太差了。