23行为型模式之访问者模式

Posted gd-luojialin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23行为型模式之访问者模式相关的知识,希望对你有一定的参考价值。

概念

  Visitor模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责。

 

角色和职责

技术图片

 

技术图片

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

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

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

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

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

 

适用于:

         把数据结构 作用于数据结构上的操作进行解耦合;

   适用于数据结构比较稳定的场合。

访问者模式总结:

  访问者模式优点是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。

  那访问者模式的缺点是是增加新的数据结构变得困难了

优缺点

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

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

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

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

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

 

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

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

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

 

案例1)

//比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。

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

class  ParkElement;
 
//不同的访问者 访问公园完成不同的动作 
class Visitor
{
public:
	virtual void visit(ParkElement *park) = 0;
};

class ParkElement //每一个
{
public:
	virtual void accept(Visitor *v) = 0;
};

class ParkA : public ParkElement
{
public:
	virtual void accept(Visitor *v)
	{
		v->visit(this);
	}
};

class ParkB : public ParkElement
{
public:
	virtual void accept(Visitor *v)
	{
		v->visit(this);
	}
};

class Park  : public ParkElement
{
public:
	Park()
	{
		m_list.clear();
	}
	void setPart(ParkElement *e)
	{
		m_list.push_back(e);
	}
public:
	void accept(Visitor *v)
	{
		for ( list<ParkElement *>::iterator it=m_list.begin(); it != m_list.end(); it++)
		{
			(*it)->accept(v);
		}
	}

private:
	list<ParkElement *> m_list;
};

class VisitorA : public Visitor
{
public:
	virtual void visit(ParkElement *park)
	{
		cout << "清洁工A访问公园A部分,打扫卫生完毕" << endl;
	}
};

class VisitorB : public Visitor
{
public:
	virtual void visit(ParkElement *park)
	{
		cout << "清洁工B 访问 公园B 部分,打扫卫生完毕" << endl;	
	}
};
class VisitorManager : public Visitor
{
public:
	virtual void visit(ParkElement *park)
	{
		cout << "管理员 检查整个公园卫生打扫情况" << endl;
	}
};

void main()
{
	VisitorA *visitorA = new VisitorA;
	VisitorB *visitorB = new VisitorB;
	
	ParkA *partA = new ParkA;
	ParkB *partB = new ParkB;

	//公园接受访问者a访问
	partA->accept(visitorA);
	partB->accept(visitorB);

	VisitorManager *visitorManager = new VisitorManager;
	Park * park = new Park;
	park->setPart(partA);
	park->setPart(partB);
	park->accept(visitorManager);

	cout<<"hello..."<<endl;
	system("pause");
	return ;
}

  

 

案例2)

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

//客户去银行办理业务
//m个客户
//n个柜员 

//将要 对象和要处理的操作分开,不同的柜员可以办理不同来访者的业务

class Element;

//访问者访问柜员 
class Visitor
{
public:
	virtual void visit(Element *element) = 0;
};


//柜员接受客户访问
class Element
{
public:
	virtual void accept(Visitor *v) = 0;
	virtual string getName() = 0;
};

//柜员A 员工
class EmployeeA : public Element
{
public:
	EmployeeA(string name)
	{
		m_name = name;
	}
	virtual void accept(Visitor *v)
	{
		v->visit(this); 
	}
	virtual string getName()
	{
		return m_name;
	}
private:
	string m_name;
};

//柜员B 员工
class EmployeeB : public Element
{
public:
	EmployeeB(string name)
	{
		m_name = name;
	}
	virtual void accept(Visitor *v)
	{
		v->visit(this);
	}
	string getName()
	{
		return m_name;
	}
private:
	string m_name;
};

class VisitorA : public Visitor
{
public:
	virtual void visit(Element *element)
	{
		cout << "通过" << element->getName() << "做A业务" << endl;
	}
};

class VisitorB : public Visitor
{
public:
	virtual void visit(Element *element)
	{
		cout << "通过" << element->getName() << "做B业务" << endl;
	}
};

void main26_01()
{
	EmployeeA *eA = new EmployeeA("柜员A");

	VisitorA *vA = new VisitorA;
	VisitorB *vB = new VisitorB;

	eA->accept(vA);
	eA->accept(vB);

	delete eA;
	delete vA;
	delete vB;
	return ;
}

//柜员B 员工
class Employees : public Element
{
public:
	Employees()
	{
		m_list = new list<Element *>;
	}
	virtual void accept(Visitor *v)
	{
		for (list<Element *>::iterator it = m_list->begin(); it != m_list->end(); it++  )
		{
			(*it)->accept(v);
		}
	}
	string getName()
	{
		return m_name;
	}
public:
	void addElement(Element *e)
	{
		m_list->push_back(e);
	}
	void removeElement(Element *e)
	{
		m_list->remove(e);
	}
private:
	list<Element *> *m_list;
	string m_name;

};

void main26_02()
{
	EmployeeA *eA = new EmployeeA("柜员A");
	EmployeeA *eB= new EmployeeA("柜员B");

	Employees *es = new Employees;
	es->addElement(eA);
	es->addElement(eB);
	VisitorA *vA = new VisitorA;
	VisitorB *vB = new VisitorB;

	es->accept(vA);
	cout << "-------------" << endl;
	es->accept(vB);

	delete eA;
	delete eB 
		;
	delete vA;
	delete vB;

	return ;
}

void main()
{
	//main26_01();
	main26_02();
	system("pause");
}

  

以上是关于23行为型模式之访问者模式的主要内容,如果未能解决你的问题,请参考以下文章

23行为型模式之访问者模式

Java开发中的23种设计模式详解之三:11种行为型模式

GoF23种设计模式之行为型模式之访问者模式

GOF 23设计模式之(行为型模式二)

10 行为型模式之 - 访问者模式

GoF23种设计模式之行为型模式之模板方法