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

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

一、访问者模式是什么?

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


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


      访问者模式的优点:


  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;
}

     程序结果如下。

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


三、总结

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

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

相关文章
|
7月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
147 0
|
2月前
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
33 3
|
7月前
|
设计模式 算法 Java
【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)
【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)
|
3月前
|
设计模式 缓存 算法
Java设计模式-访问者模式(22)
Java设计模式-访问者模式(22)
|
5月前
|
设计模式 C++
C++一分钟之-设计模式:工厂模式与抽象工厂
【7月更文挑战第14天】设计模式是解决软件设计问题的通用方案。工厂模式与抽象工厂模式是创建型模式,用于对象创建而不暴露创建逻辑。工厂模式推迟实例化到子类,但过度使用会增加复杂性。抽象工厂则创建相关对象族,但过度抽象可能造成不必要的复杂度。两者均应按需使用,确保设计灵活性。代码示例展示了C++中如何实现这两种模式。
47 3
|
5月前
|
设计模式 安全 C++
C++一分钟之-C++中的设计模式:单例模式
【7月更文挑战第13天】单例模式确保类只有一个实例,提供全局访问。C++中的实现涉及线程安全和生命周期管理。基础实现使用静态成员,但在多线程环境下可能导致多个实例。为解决此问题,采用双重检查锁定和`std::mutex`保证安全。使用`std::unique_ptr`管理生命周期,防止析构异常和内存泄漏。理解和正确应用单例模式能提升软件的效率与可维护性。
65 2
|
7月前
|
设计模式 开发框架 算法
C++中的设计模式:基本概念与应用
C++中的设计模式:基本概念与应用
72 2
|
7月前
|
设计模式 安全 Java
【设计模式】字节三面:请举例阐释访问者模式
【设计模式】字节三面:请举例阐释访问者模式
49 2
|
7月前
|
设计模式 算法 Java
23种设计模式,访问者模式的概念优缺点以及JAVA代码举例
【4月更文挑战第10天】访问者模式是一种将算法与对象结构分离的设计模式。这种模式主要用于执行一个操作(或一组操作)在一个对象结构的各元素上,它可以在不修改各元素的类的前提下定义新的操作。
57 2
|
7月前
|
设计模式 算法 中间件
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
222 1

热门文章

最新文章

  • 1
    设计模式转型:从传统同步到Python协程异步编程的实践与思考
    59
  • 2
    C++一分钟之-设计模式:工厂模式与抽象工厂
    47
  • 3
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    54
  • 4
    C++一分钟之-C++中的设计模式:单例模式
    65
  • 5
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    43
  • 6
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    70
  • 7
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    62
  • 8
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    43
  • 9
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    52
  • 10
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    121