什么是访问者模式?
Definition: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.
访问者模式最合适的使用情况是需要对一个家族的对象逐个访问,并根据具体的对象做出不同的操作,而且不希望改变原来的对象。当然在设计的时候需要让家族成员定义一个支持访问者模式的接口,即accept函数。以后需要添加新功能的时候只要增加相应的具体访问者类。
当然访问者模式也有缺点,比如家族类里面新加了成员,每个具体访问者类也需要相应改变;类的状态对访问者完全透明,违背数据隐藏原则。等等
访问者模式有用到双分配(double-dispatch)技术,由于Client使用的是抽象类Element和Visitor,无法达到对具体的Element调用相应的visit函数,需要在Element类的函数accept中转发visitor.visit(this),此时this是一个具体的类,能够调用到正确的函数。
类图结构:
Example:
例子模式对班级活动收费,但是男生收费是女生费用的2倍。在不能向Student中添加函数的情况下,可以使用访问者模式。
people.h代码如下:
#ifndef __PEOPLE_H__#define __PEOPLE_H__#includeclass IVisitor;class People{public: People(std::string strName, int nMoney) : m_strName(strName), m_nMoney(nMoney) {} void pay(int nMoneyToPay); virtual void accept(IVisitor* pVisitor) = 0; const std::string& getName() const;private: int m_nMoney; std::string m_strName;};class Man : public People{public: Man(std::string strName, int nMoney) : People(strName, nMoney) {} virtual void accept(IVisitor* pVisitor);};class Woman : public People{public: Woman(std::string strName, int nMoney) : People(strName, nMoney) {} virtual void accept(IVisitor* pVisitor);};#endif
people.cpp代码如下:
#include "people.h"#include "visitor.h"#includevoid People::pay( int nMoneyToPay ){ m_nMoney -= nMoneyToPay;}const std::string& People::getName() const{ return m_strName;}void Man::accept( IVisitor* pVisitor ){ pVisitor->visit(this);}void Woman::accept( IVisitor* pVisitor ){ pVisitor->visit(this);}
visitor.h代码如下:
#ifndef __VISITOR_H__#define __VISITOR_H__class Man;class Woman;class IVisitor{public: virtual void visit(Man* pMan) = 0; virtual void visit(Woman* pWoman) = 0;};class ChargeMoneyVisitor : public IVisitor{public: ChargeMoneyVisitor() : m_nSum(0) {} virtual void visit(Man* pMan); virtual void visit(Woman* pWoman); int getSum() const;private: int m_nSum; static const int PAY = 10;};#endif
visitor.cpp代码如下:
#include "visitor.h"#include "people.h"#includevoid ChargeMoneyVisitor::visit( Man* pMan ){ int nMoneyToCharge = 2*PAY; pMan->pay(nMoneyToCharge); m_nSum += nMoneyToCharge; std::cout << pMan->getName() << " is charged " << nMoneyToCharge << " RMB\n";}void ChargeMoneyVisitor::visit( Woman* pWoman ){ int nMoneyToCharge = PAY; pWoman->pay(nMoneyToCharge); m_nSum += nMoneyToCharge; std::cout << pWoman->getName() << " is charged " << nMoneyToCharge << " RMB\n";}int ChargeMoneyVisitor::getSum() const{ return m_nSum;}
main.cpp代码如下:
#include "visitor.h"#include "people.h"#include#include int main(){ std::vector students; students.push_back(new Man("Bob", 100)); students.push_back(new Woman("Lily", 100)); ChargeMoneyVisitor chargeMoneyVisitor; std::vector ::const_iterator iter = students.begin(); for (; iter != students.end(); ++iter) { People* pPeople = *iter; pPeople->accept(&chargeMoneyVisitor); } std::cout << "Total charge money: " << chargeMoneyVisitor.getSum() << " RMB\n"; iter = students.begin(); for (; iter != students.end(); ++iter) { delete *iter; } return 0;}
运行结果如下: