c++设计模式-----访问者模式visitor

本文通过银行柜台业务的例子详细介绍了访问者模式的概念、应用场景及其在C++中的实现方式。该模式允许在不修改元素类的前提下为对象结构添加新的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

访问者模式例子:

       我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。我们的访问者模式可以很好付诸在这个场景中:对于银行柜台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们作为访问者,今天来银行可能是取消费流水,明天来银行可能是去办理手机银行业务,这些是我们访问者的操作,一直是在变化的。

           

访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 

    类图和样例:


抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。

具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。

抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。

具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。

结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。

#include <iostream>
#include <string>
#include <list>
using namespace std;

class Element;

class Visitor
{
public:
	virtual void Visit(Element *element){};
};

// "Element"
class Element
{
public:
	// Methods
	virtual void Accept(Visitor *visitor){};
};


// "ConcreteElement"
class Employee : public Element
{
public:
	string name;
	double income;
	int vacationDays;

public:
	Employee(string name, double income,
		int vacationDays)
	{
		this->name = name;
		this->income = income;
		this->vacationDays = vacationDays;
	}

	void Accept(Visitor *visitor)
	{
		visitor->Visit(this);
	}
};

class IncomeVisitor : public Visitor
{
public:
	void Visit(Element *element)
	{
		Employee *employee = ((Employee*)element);
		employee->income *= 1.10;
		cout << employee->name << " 's new income: " << employee->income << endl;

	}
};

class VacationVisitor : public Visitor
{
public:
	void Visit(Element *element)
	{
		Employee *employee = ((Employee*)element);
		// Provide 3 extra vacation days
		employee->vacationDays += 3;
		cout << employee->name << " 's new vacation days: " << employee->income << endl;
	}
};

// "ObjectStructure"
class Employees
{
private:
	list< Employee*> employees;

public:

	void Attach(Employee *employee)
	{
		employees.push_back(employee);
	}

	void Detach(Employee *employee)
	{
		employees.remove(employee);
	}

	void Accept(Visitor *visitor)
	{
		for (std::list<Employee*>::iterator it = employees.begin(); it != employees.end(); ++it)
			(*it)->Accept(visitor);
	}
};

void main()
{
	Employees *e = new Employees();
	e->Attach(new Employee("Tom", 25000.0, 14));
	e->Attach(new Employee("Thomas", 35000.0, 16));
	e->Attach(new Employee("Roy", 45000.0, 21));

	// Create two visitors
	IncomeVisitor *v1 = new IncomeVisitor();
	VacationVisitor *v2 = new VacationVisitor();

	// Employees are visited
	e->Accept(v1);
	e->Accept(v2);
}

优缺点:

访问者模式有如下的优点:

1访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。

2访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。

3访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。

4积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。

访问者模式有如下的缺点:

1增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。

2破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。

本文转载自:http://blog.youkuaiyun.com/lcl_data/article/details/11607377

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值