3.11.1功能
在面向对象系统的开发和设计过程,经常会遇到一种情况就是需求变更(ChangeRequest),经常我们做好的一个设计、实现了一个系统原型,咱们的客户又会有了新的需求。我们又因此不得不去修改已有的设计,最常见就是解决方案就是给已经设计、实现好的类添加新的方法去实现客户新的需求,这样就陷入了设计变更的梦魇:不停地打补丁,其带来的后果就是设计根本就不可能封闭、编译永远都是整个系统代码。
Visitor模式则提供了一种解决方案:将更新(变更)封装到一个类中(Vistor),并由待更改类提供一个接收接口,则可达到效果。
3.11.2 结构图
• Vi s i t o r(访问者,如N o d e Vi s i t o r)
— 为该对象结构中C o n c r e t e E l e m e n t的每一个类声明一个Vi s i t 操作。该操作的名字和特征标识了发送Vi s i t 请求给哪个访问者。
• C o n c r e t e Vi s i t o r(具体访问者,如 Ty p e C h e c k i ng Vi s i t o r)
— 实现每个由Vi s i t o r 声明的操作。每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。
• E l e m e n t(元素,如 N o d e)
— 定义一个Ac c e p t操作,它以一个访问者为参数。
• C o n c r e t e E l e m e n t(具体元素,如As s i g n m e n t N o d e,Va r i a b l e R e f N o d e)
— 实现Ac c e p t操作,该操作以一个访问者为参数。
• O b j e c t S t r u c t u r e
— 能枚举它的元素。
— 可以提供一个高层的接口以允许该访问者访问它的元素。
— 可以是一个复合(参见C o m p o s i t e(4. 3) )或是一个集合,如一个列表或一个无序集合。
3.11.3 协作
• 一个使用Vi s i t o r 模式的客户必须创建一个C o n c r e t e Vi s i t o r对象,然后遍历该对象结构,并用该访问者访问每一个元素。
• 当一个元素被访问时,它调用对应于它的类的Vi s i t o r操作。如果必要,该元素将自身作为这个操作的一个参数以便该访问者访问它的状态。
3.11.4 C++代码示例
//Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
class ConcreteElementA;
class ConcreteElementB;
class Element;
class Visitor
{
public:
virtual ~Visitor();
virtual void
VisitConcreteElementA(Element* elm) = 0;
virtual void
VisitConcreteElementB(Element* elm) = 0;
protected:
Visitor();
private:
};
class ConcreteVisitorA :public Visitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual void
VisitConcreteElementA(Element* elm);
virtual void
VisitConcreteElementB(Element* elm);
protected:
private:
};
class ConcreteVisitorB :public Visitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual void
VisitConcreteElementA(Element* elm);
virtual void
VisitConcreteElementB(Element* elm);
protected:
private:
};
#endif //~_VISITOR_H_
//Visitor.cpp
#include "Visitor.h"
#include "Element.h"
#include <iostream>
using namespace std;
Visitor::Visitor()
{
}
Visitor::~Visitor()
{
}
ConcreteVisitorA::ConcreteVisitorA()
{
}
ConcreteVisitorA::~ConcreteVisitorA()
{
}
void ConcreteVisitorA::VisitConcreteElementA(Element* elm)
{
cout << "i willvisit ConcreteElementA..."<<endl;
}
void
ConcreteVisitorA::VisitConcreteElementB(Element*elm)
{
cout << "i will visitConcreteElementB..."<<endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{
}
ConcreteVisitorB::~ConcreteVisitorB()
{
}
void ConcreteVisitorB::VisitConcreteElementA(Element* elm)
{
cout << "i will visitConcreteElementA..."<<endl;
}
void ConcreteVisitorB::VisitConcreteElementB(Element* elm)
{
cout << "i will visit ConcreteElementB..."<<endl;
}
//Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
class Visitor;
class Element
{
public:
virtual ~Element();
virtual void Accept(Visitor*vis) = 0;
protected:
Element();
private:
};
class ConcreteElementA :public Element
{
public:
ConcreteElementA();
~ConcreteElementA();
void Accept(Visitor* vis);
protected:
private:
};
class ConcreteElementB :public Element
{
public:
ConcreteElementB();
~ConcreteElementB();
void Accept(Visitor* vis);
protected:
private:
};
#endif //~_ELEMENT_H_
//Element.cpp
#include"Element.h"
#include"Visitor.h"
#include<iostream>
using namespace std;
Element::Element()
{
}
Element::~Element()
{
}
void Element::Accept(Visitor*vis)
{
}
ConcreteElementA::ConcreteElementA()
{
}
ConcreteElementA::~ConcreteElementA()
{
}
void ConcreteElementA::Accept(Visitor* vis)
{
vis->VisitConcreteElementA(this);
cout << "visiting ConcreteElementA..."<<endl;
}
ConcreteElementB::ConcreteElementB()
{
}
ConcreteElementB::~ConcreteElementB()
{
}
void ConcreteElementB::Accept(Visitor* vis)
{
cout << "visiting ConcreteElementB..."<<endl;
vis->VisitConcreteElementB(this);
}
//main.cpp
#include"Element.h"
#include"Visitor.h"
#include<iostream>
using namespace std;
int main(int argc, char*argv[])
{
Visitor* vis = new ConcreteVisitorA();
Element*elm = new
ConcreteElementA();
elm->Accept(vis);
return 0;
}