设计模式之访问者模式(C++)

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

一、访问者模式是什么?

       访问者模式是一种行为型的软件设计模式,表示一个作用于某对象结构中的各元素的操作。使得在不改变各元素类的前提下,能定义作用于这些元素的操作。

       该模式适合数据结构相对稳定且算法又易变化的系统。数据结构是被访问者,算法操作相当于访问者。

       访问者模式的优点:

  1. 良好扩展性。扩展对元素的操作,只需要添加访问者。
  2. 满足单一职责原则。相关的操作封装为一个访问者,使得访问者职责单一。
  3. 解耦。数据结构自身和作用于它的操作解耦合。

       访问者模式的缺点:

  1. 不易增加元素类。每增加一个元素类,访问者的接口和实现都要进行变化。
  2. 违背了依赖倒置原则。访问者依赖的是具体元素而不是抽象元素。
  3. 破坏封装。访问者可以获取被访问元素的细节。

二、访问者模式

2.1 结构图

       客户端即Main主函数,对象结构中存放了被访问的元素集合以及遍历各个元素的方法,使得抽象访问者可以依次与具体元素对接,完成访问。

2.2 代码示例

       场景描述:市长视察学校和企业。

//Visitor.h
/****************************************************/
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class Visitor;

// 抽象元素类-地点(被访问)
class Place 
{
public:
	// 构造函数
	Place(string name) : m_name(name) {}

	// 接受访问
	virtual void accept(Visitor* visitor) = 0;

	// 获取名字
	string getName() {
		return m_name;
	}

private:
	string m_name;
};

// 具体元素类-学校
class School : public Place 
{
public:
	// 构造函数
	School(string name) : Place(name) {}

	// 接受访问
	virtual void accept(Visitor* visitor);

};

// 具体元素类-企业
class Enterprise : public Place 
{
public:
	// 构造函数
	Enterprise(string name) : Place(name) {}

	// 接受访问
	virtual void accept(Visitor* visitor);

};

// 抽象访问者
class Visitor 
{
public:
	// 访问学校
	virtual void visitSchool(School* school) = 0;

	// 访问企业
	virtual void visitEnterprise(Enterprise* enterprise) = 0;

};

// 具体访问者-市长
class Mayor : public Visitor 
{
public:
	// 访问学校
	virtual void visitSchool(School* school) {
		cout << "市长参观了:" << school->getName() << endl;
		cout << "对老师和学生表达了诚挚的慰问。" << endl;
	}

	// 访问企业
	virtual void visitEnterprise(Enterprise* enterprise) {
		cout << "市长参观了:" << enterprise->getName() << endl;
		cout << "对企业的发展表示肯定。" << endl;
	}

};

// 访问行为类
class Visiting
{
public:
	// 添加被访问地点
	void add(Place* place) {
		places.push_back(place);
	}

	// 删除被访问地点
	void remove(Place* place) {
		places.erase(std::remove(places.begin(), places.end(), place), places.end());
	}

	// 进行访问
	void accept(Visitor* visitor) {
		for (auto place : places) {
			place->accept(visitor);
		}
	}

private:
	std::vector<Place*> places;
};
//Visitor.cpp
/****************************************************/
#include "Visitor.h"

// 接受访问
void School::accept(Visitor* visitor) {
	visitor->visitSchool(this);
}

// 接受访问
void Enterprise::accept(Visitor* visitor) {
	visitor->visitEnterprise(this);
}
//main.cpp
/****************************************************/
#include <iostream>
#include <string>
#include "Visitor.h"

using namespace std;

int main() 
{
	Visiting *visiting = new Visiting();
	Place *school = new School("东华大学");
	Place *enterprise = new Enterprise("华为");
	Visitor *mayor = new Mayor();

	// 添加被访问对象
	cout << "首日,";
	visiting->add(school);
	visiting->add(enterprise);
	// 安排市长进行访问
	visiting->accept(mayor);
	// 次日行程,删除某个被访问对象后再次访问
	cout << "次日,";
	visiting->remove(school);
	visiting->accept(mayor);

	// 删除
	delete visiting;
	delete school;
	delete enterprise;
	delete mayor;
	visiting = nullptr;
	school = nullptr;
	enterprise = nullptr;
	mayor = nullptr;

	return 0;
}

       程序结果如下。

       访问者模式使得访问操作与被访问元素解耦,同样是访问学校和企业,不同的访问者来干的事情和目的是不一样的,而这个不同的内容就可以在访问者类中实现。不过该模式不太适合增加新的元素,就像添加一个新的被访问对象-派出所,那每个访问者都要添加访问派出所的操作,违反了开闭原则。

三、总结

       我尽可能用较通俗的话语和直观的代码例程,来表述我对访问者模式的理解,或许有考虑不周到的地方,如果你有不同看法欢迎评论区交流!希望我举的例子能帮助你更好地理解访问者模式。

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

猜你喜欢

转载自blog.csdn.net/zhaitianbao/article/details/130319735