在开发时有时会遇到需求变动,这样就要经常去修改已有的设计。比较常见的是在实现好的类中添加新方法满足客户新需求。这时可以使用Visitor模式。
Visitor 模式则提供了一种解决方案:将更新封装到一个类中,并由待更改类提供一个接收接口,来实现目的。
这里对对象(ConcreteElement)添加了一个统一的接口:Accept函数,来接收一个访问者对象。通过参数Visitor把对对象的操作移到类外。通过调用Visitor的接口函数visitConcreteElement针对当前对象进行操作。
函数Accept()是个双分派操作。调用哪一个Accept由Element类型和Visitor类型决定。
Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
class ConcreteElementA;
class ConcreteEnementB;
class Element;
class Visitor
{
public:
virtual ~Visitor();
virtual void VisitConcreteElementA(Element* elm) = 0;
virtual void VisitConcreteElementB(Element* eml) = 0;
protected:
Visitor();
};
class ConcreteVisitorA :public Visitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual void VisitConcreteElementA(Element* elm) ;
virtual void VisitConcreteElementB(Element* eml) ;
};
class ConcreteVisitorB :public Visitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual void VisitConcreteElementA(Element* elm);
virtual void VisitConcreteElementB(Element* eml);
};
#endif
Visitor.cpp
#include "Visitor.h"
#include "Element.h"
#include <iostream>
Visitor::Visitor()
{}
Visitor::~Visitor()
{}
ConcreteVisitorA::ConcreteVisitorA()
{}
ConcreteVisitorA::~ConcreteVisitorA()
{}
void ConcreteVisitorA::VisitConcreteElementA(Element* elm)
{
std::cout << "i will visit ConcreteElementA." << std::endl;
}
void ConcreteVisitorA::VisitConcreteElementB(Element* elm)
{
std::cout << "i will visit ConcreteElementB." << std::endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{}
ConcreteVisitorB::~ConcreteVisitorB()
{}
void ConcreteVisitorB::VisitConcreteElementA(Element* elm)
{
std::cout << "i will visit ConcreteElementA." << std::endl;
}
void ConcreteVisitorB::VisitConcreteElementB(Element* elm)
{
std::cout << "i will visit ConcreteElementB." << std::endl;
}
Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
class Visitor;
class Element
{
public:
virtual ~Element();
virtual void Accept(Visitor* vis) = 0;
protected:
Element();
};
class ConcreteElementA :public Element
{
public:
ConcreteElementA();
~ConcreteElementA();
void Accept(Visitor* vis);
};
class ConcreteElementB :public Element
{
public:
ConcreteElementB();
~ConcreteElementB();
void Accept(Visitor* vis);
};
#endif
Element.cpp
#include "Element.h"
#include "Visitor.h"
#include <iostream>
Element::Element()
{}
Element::~Element()
{}
void Element::Accept(Visitor* vis)
{}
ConcreteElementA::ConcreteElementA()
{}
ConcreteElementA::~ConcreteElementA()
{}
void ConcreteElementA::Accept(Visitor* vis)
{
vis->VisitConcreteElementA(this);
std::cout << "visiting ConcreteElementA." << std::endl;
}
ConcreteElementB::ConcreteElementB()
{}
ConcreteElementB::~ConcreteElementB()
{}
void ConcreteElementB::Accept(Visitor* vis)
{
vis->VisitConcreteElementB(this);
std::cout << "visiting ConcreteElementB." << std::endl;
}
main.cpp
#include "Element.h"
#include "Visitor.h"
#include <iostream>
int main()
{
Visitor* vis = new ConcreteVisitorA();
Element* elm = new ConcreteElementA();
elm->Accept(vis);
return 0;
}