问题:
在面向对象系统的开发和设计过程中,经常会遇到一种情况就是需求变更,这样我们不得不去修改已有的设计,最常见的方法就是在实现好的类添加新的方法去实现客户新的需求,这样造成原来的设计根本就不可能封闭;
意图:
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用环境:
u 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
u 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor 使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor 模式让每个应用仅包含需要用到的操作。
u 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
结构:
实现:
Element.h文件
#pragma once
class Visitor;
class Element
{
public:
Element(void);
virtual ~Element(void);
virtual void Accept(Visitor*vis)=0;
};
class ConcreteElementA:publicElement
{
public:
ConcreteElementA();
~ConcreteElementA();
void Accept(Visitor *vis);
};
class ConcreteElementB:publicElement
{
public:
ConcreteElementB();
~ConcreteElementB();
void Accept(Visitor *vis);
};
Element.cpp文件
#include "StdAfx.h"
#include "Element.h"
#include "Visitor.h"
#include <iostream>
using namespace std;
Element::Element(void)
{
}
Element::~Element(void)
{
}
void Element::Accept(Visitor *vis)
{
}
ConcreteElementA::ConcreteElementA()
{
}
ConcreteElementA::~ConcreteElementA()
{
}
void ConcreteElementA::Accept(Visitor *vis)
{
vis->visitConcreteElementA(this);
cout<<"visitingConcreteElementA...."<<endl;
}
ConcreteElementB::ConcreteElementB()
{
}
ConcreteElementB::~ConcreteElementB()
{
}
void ConcreteElementB::Accept(Visitor *vis)
{
vis->visitConcreteElementB(this);
cout<<"visitingConcreteElementB...."<<endl;
}
Visitor.h文件
#pragma once
class ConcreteElementA;
class ConcreteElementA;
class Element;
class Visitor
{
public:
Visitor(void);
virtual ~Visitor(void);
virtual void visitConcreteElementA(Element*elm)=0;
virtual void visitConcreteElementB(Element*elm)=0;
};
class ConcreteVisitorA:publicVisitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual void visitConcreteElementA(Element*elm);
virtual void visitConcreteElementB(Element*elm);
};
class ConcreteVisitorB:publicVisitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual void visitConcreteElementA(Element*elm);
virtual void visitConcreteElementB(Element*elm);
};
Visitor.cpp文件
#include "StdAfx.h"
#include "Visitor.h"
#include "Element.h"
#include <iostream>
using namespace std;
Visitor::Visitor(void)
{
}
Visitor::~Visitor(void)
{
}
ConcreteVisitorA::ConcreteVisitorA()
{
}
ConcreteVisitorA::~ConcreteVisitorA()
{
}
void ConcreteVisitorA::visitConcreteElementA(Element *elm)
{
cout<<"iwill visit ConcreteElementA...."<<endl;
}
void ConcreteVisitorA::visitConcreteElementB(Element *elm)
{
cout<<"iwill visit ConcreteElementB...."<<endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{
}
ConcreteVisitorB::~ConcreteVisitorB()
{
}
void ConcreteVisitorB::visitConcreteElementA(Element *elm)
{
cout<<"iwill visit ConcreteElementA...."<<endl;
}
void ConcreteVisitorB::visitConcreteElementB(Element *elm)
{
cout<<"iwill visit ConcreteElementB...."<<endl;
}
调用主函数:
// VisitorPattern.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Visitor.h"
#include "Element.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Visitor *vis=new ConcreteVisitorA();
Element *elm=new ConcreteElementA();
elm->Accept(vis);
return 0;
}
代码理解:
在Visitor模式中Accept()操作时一个双分派的操作。具体调用哪一个具体的Accept()操作,有2个决定因素:1)Element的类型。因为Accept()是多态的操作,需要具
体的Element 类型的子类才可以决定到底调用哪一个 Accept()实现;2)Visitor的类型。
Accept()操作有一个参数(Visitor*vis) ,要决定了实际传进来的 Visitor 的实际类别才
以决定具体是调用哪个VisitConcrete()实现。