////////////////////////////////////////////////////////////////////////////////////
// Visitor pattern
// - Represent an operation to be performed on the elements of an object structure.
// Visitor lets you define a new operation without changing the classes of the
// elements on which it operates.
//
// For example:
// - 爸爸(ConcreteVisitor1)帶着兒子(ConcreteVisitor2)去書店(ConcreteElementA)買書,
// 爸爸買了一套《平凡的世界》(ConcreteVisitor1::VisitConcreteElementA),
// 兒子買了一本《安徒生童話集》(ConcreteVisitor2::VisitConcreteElementA)。
// 從書店出來,兒子說渴了,爸爸便帶着兒子去附近的超市(ConcreteElementB),
// 父親買了一瓶礦泉水(ConcreteVisitor1::VisitConcreteElementB),
// 兒子買了一瓶爽歪歪(ConcreteVisitor2::VisitConcreteElementB)。
// 如果是爸爸媽媽兒子三人出門,在上述的基礎上,增加一個ConcreteVisitor3(媽媽),再分別實現
// ConcreteVisitor3::VisitConcreteElementA(媽媽買了一本《一週一樣拿手菜》)
// ConcreteVisitor3::VisitConcreteElementB(媽媽買了一杯《珍珠奶茶》)即可。
//
// Author : ZAsia
// Date : 15/05/20
// Warning : In practice, declaration and implementation should
// be separated(.h and .cpp).
/////////////////////////////////////////////////////////////////////////////////////
#include
#include
using namespace std;
class ConcreteElementA;
class ConcreteElementB;
// Visitor
// - declares a Visit operation for each class of ConcreteElement in the object
// structure. The operation's name and signature identifies the class that sends
// the Visit request to the visitor. That lets the visitor determine the concrete
// the concrete class of the element being visited. Then the visitor can access the
// element directly through its particular interface.
class Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA) = 0;
virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB) = 0;
};
// ConcreteVisitor
// - implements each oepration declared by Visitor. Each operation implements
// a fragment of the algorithm defined for the corresponding class of object
// in the structure. ConcreteVisitor provides the context for the algorithm
// and stores its local state. This state often accumulates results during
// the traversal of the structure.
class ConcreteVisitor1 : public Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA)
{
cout << "ConcreteVisitor1::VisitConcreteElementA..." << endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB)
{
cout << "ConcreteVisitor1::VisitConcreteElementB..." << endl;
}
};
class ConcreteVisitor2 : public Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA)
{
cout << "ConcreteVisitor2::VisitConcreteElementA..." << endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB)
{
cout << "ConcreteVisitor2::VisitConcreteElementB..." << endl;
}
};
// Element
// - defines an Accept operation that takes a visitor as an argument.
class Element
{
public:
virtual void Accept(Visitor *visitor) = 0;
};
// ConcreteElement
// - implements an Accept operation that takes a visitor as an argument.
class ConcreteElementA : public Element
{
public:
virtual void Accept(Visitor *visitor)
{
visitor->VisitConcreteElementA(this);
}
};
class ConcreteElementB : public Element
{
public:
virtual void Accept(Visitor *visitor)
{
visitor->VisitConcreteElementB(this);
}
};
// ObjectStructure
// - can enumerate its elements.
// - may provide a high-level interface to allow the visitor to visit its elements.
// - may either be a composite or a collection such as a list or a set.
class ObjectStructure
{
public:
void Accept(Visitor *visitor)
{
for (list::iterator iter = _elements.begin();
iter != _elements.end(); ++iter)
{
(*iter)->Accept(visitor);
}
}
void Attach(Element *element)
{
_elements.push_back(element);
}
void Detach(Element *element)
{
_elements.remove(element);
}
private:
list _elements;
};
// Collaborations
// - A client that uses the Visitor pattern must create a ConcreteVisitor object and
// than traverse the object structure, visiting each element with the visitor.
// - When an element is visited, it calls the Visitor operation that corresponds to
// its class. The element supplies itself as an argument to this operaton to let the
// visitor access its state, if neccessary.
int main()
{
ConcreteElementA *pConcreteElementA = new ConcreteElementA();
ConcreteElementB *pConcreteElementB = new ConcreteElementB();
ObjectStructure *pObjectStructure = new ObjectStructure();
pObjectStructure->Attach(pConcreteElementA);
pObjectStructure->Attach(pConcreteElementB);
ConcreteVisitor1 *pConcreteVisitor1 = new ConcreteVisitor1();
pObjectStructure->Accept(pConcreteVisitor1);
pObjectStructure->Detach(pConcreteElementB);
ConcreteVisitor2 *pConcreteVisitor2 = new ConcreteVisitor2();
pObjectStructure->Accept(pConcreteVisitor2);
delete pConcreteElementA;
delete pConcreteElementB;
delete pObjectStructure;
delete pConcreteVisitor1;
delete pConcreteVisitor2;
return 0;
}
////////////////////////////////////////////////////////////////////////////
// 1.Visitor makes adding new operations easy. You can define a new operation
// over an object structure simply by adding a new visitor.
// 2.A visitor gathers related operations and separates unrelated ones. Related
// behavior isn't spread over the classes defining the object structure; it's
// localized in a visitor. Unrelated sets of behavior are partitioned in their
// own visitor subclasses. That simplies both the classes defining the element
// and the algorithms defined in the visitors. Any algorithm-specific data
// structures can be hidden in the visitor.
// 3.Add new ConcreteElement classes is hard. Each new ConcreteElement gives rise
// to a new abstract operation on Visitor and a corresponding implementation in
// every ConcreteVisitor class.
// 4.Each Visit operation on the Visitor declares its argument to be a particular
// ConcreteElement, allowing the Visitor to access the interface fo the ConcreteElement
// directly. ConcreteVisitor classes override each Visit operation to implement
// visitor-specific behavior for the corresponding ConcreteElement class.
// 5.Double dispatch. The operation that gets executed depends on both the type of
// Visitor and the type of Element it visits. Instead of binding operations
// statically into the Element interface, you can consolidate the operations in a
// Visitor and use Accept to do the binding at run-time. Extending the Element
// interface amounts to defining one Visitor subclass rather than many new Element
// subclasses.
DesignPatterns_Visitor
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.