设计模式系列7-----C++实现访问者模式(Visitor Pattern)

什么是访问者模式?

      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__

#include <string>

class 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"
#include <iostream>

void 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"
#include <iostream>

void 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 <vector>
#include <iostream>

int main()
{
	std::vector<People*> students;
	students.push_back(new Man("Bob", 100));
	students.push_back(new Woman("Lily", 100));

	ChargeMoneyVisitor chargeMoneyVisitor;

	std::vector<People*>::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;
}

 

运行结果如下:

image

posted on 2011-12-11 00:38  GraphicsMe  阅读(3247)  评论(0编辑  收藏  举报

导航