设计模式-访问者模式

2023-11-09

1、访问者模式被称为最复杂的设计模式。

访问者模式访问者模式( Visitor pattern)是一种将数据结构与数据操作分离的设计模式。是指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。属于行为型模式。

访问者模式被称为最复杂的设计模式,并且使用频率不高,设计模式的作者也评价为:大多情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就真的需要使用了。访问者模式的基本思想是,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个 accept()方法用来接受访问者对象的访问。

不同的访问者对同一元素的访问内容不同,使得相同的元素集合可以产生不同的数据结果。 accept()方法可以接收不同的访问者对象然后在内部将自己(元素)转发到接收到的访问者对象的vsit()方法内。访问者内部对应类型的vst()方法就会得到回调执行,对元素进行操作。也就是通过两次动态分发(第一次是对访问者的分发aept()方法,第二次是对元素的分发ⅵsit()方法),才最终将一个具体的元素传递到一个具体的访问者。如此一来,就解耦了数据结构与操作,且数据操作不会改变元素状态。访问者模式的核心是,解耦数据结构与数据操作,使得对元素的操作具备优秀的扩展性。可以通过扩展不同的数据操作类型(访问者)实现对相同元素集的不同的操作。

利用访问者模式实现KP考核的场景为例:

package com.lx.designPattern.visitorpattern.kpi;

/**
 * @program: People
 * @description: 访问者接口
 * @author: liu wei ping
 * @create: 2022-05-22 13:51
 */
public interface IVisitor {

    void visit(Engineer engineer);

    void visit(Manager manager);
}


package com.lx.designPattern.visitorpattern.kpi;

/**
 * @program: People
 * @description: CEO访问者
 * @author: liu wei ping
 * @create: 2022-05-22 13:48
 */
public class CEOVistitor implements IVisitor{
    public void visit(Engineer engineer) {
        System.out.println("工程师" + engineer.name + ". KPI:" + engineer.kpi);

    }

    public void visit(Manager manager) {
        System.out.println("经理:" + manager.name + ",KPI:" + manager.kpi + ". 产品数量:" + manager.getProducts());
    }
}


package com.lx.designPattern.visitorpattern.kpi;

/**
 * @program: People
 * @description: CTO访问者
 * @author: liu wei ping
 * @create: 2022-05-22 13:49
 */
public class CTOVistitor implements IVisitor{
    @Override
    public void visit(Engineer engineer) {
        System.out.println("工程师" + engineer.name + ", 代码行数" + engineer.getCodeLines());
    }

    public void visit(Manager manager) {
        System.out.println("" + manager.name + ". 产品数量" + manager.getProducts());
    }
}
package com.lx.designPattern.visitorpattern.kpi;

import java.util.Random;

/**
 * @program: People
 * @description: 员工
 * @author: liu wei ping
 * @create: 2022-05-22 13:49
 */
public abstract   class Employee {
    public String name;
    public int kpi; //员工KPI

    public Employee(String name) {
        this.name = name;
        kpi = new Random().nextInt(10);
    }

    //接收访问者的访问
    public  abstract void accept(IVisitor visitor);
}


package com.lx.designPattern.visitorpattern.kpi;

import java.util.Random;

/**
 * @program: People
 * @description: 工程师
 * @author: liu wei ping
 * @create: 2022-05-22 13:50
 */
public class Engineer extends Employee{

    public Engineer(String name) {
        super(name);
    }

    @Override
    public void accept(IVisitor visitor) {
         visitor.visit(this);
    }

    public int getCodeLines(){
        return  new Random().nextInt(10*10000);
    }

}


package com.lx.designPattern.visitorpattern.kpi;

import java.util.Random;

/**
 * @program: People
 * @description: 经理
 * @author: liu wei ping
 * @create: 2022-05-22 13:51
 */
public class Manager extends Employee{

    public Manager(String name) {
        super(name);
    }

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }

    //考核的是每年新产品研发数量
    public int  getProducts(){
        return new Random().nextInt(10);
    }

}
package com.lx.designPattern.visitorpattern.kpi;

import java.util.LinkedList;
import java.util.List;

/**
 * @program: People
 * @description: 业务报表数据
 * @author: liu wei ping
 * @create: 2022-05-22 13:48
 */
public class BusinessReport {
    private List<Employee> employees = new LinkedList<Employee>();

    public  BusinessReport(){
        employees.add(new Manager("产品经理A"));
        employees.add(new Engineer("程序员A"));
        employees.add(new Engineer("程序员B"));
        employees.add(new Engineer("程序员C"));
        employees.add(new Manager("产品经理B"));
        employees.add(new Engineer("程序员D"));
    }

    public  void showReport(IVisitor visitor){
        for (Employee employee : employees) {
            employee.accept(visitor);
        }
    }



}
package com.lx.designPattern.visitorpattern.kpi;

/**
 * @program: People
 * @description: 访问者模式测试类
 * @author: liu wei ping
 * @create: 2022-05-22 13:52
 */
public class Test {
    public static void main(String[] args) {
        BusinessReport report = new BusinessReport();
        System.out.println("===========CEO看报表=============");
        report.showReport(new CEOVistitor());
        System.out.println("===========CTO看报表=============");
        report.showReport(new CTOVistitor());

    }
}

测试结果如下图:

访问者模式的优缺点

优点:

1、解耦了数据结构与数据操作,使得操作集合可以独立变化;

2、扩展性好:可以通过扩展访问者角色,实现对数据集的不同操作;

3、元素具体类型并非单一,访问者均可操作

4、各角色职责分离,符合单一职责原则。

缺点:

1、无法增加元素类型:若系统数据结构对象易于变化,经常有新的数据对象增加进来,则访问者类必须增加对应元素类型的操作,违背了开闭原则;

2、具体元素变更困难∶具体元素增加属性,删除属性等操作会导致对应的访问者类需要进行相应的修改,尤其当有大量访问者类时,修改范围太大;

3、违背依赖倒置原则:为了达到”区别对待“,访问者依赖的是具体元素类型,而不是抽象。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式-访问者模式 的相关文章

  • C++设计模式(8)——命令模式

    命令模式 亦称 动作 事务 Action Transaction Command 意图 命令模式是一种行为设计模式 它可将请求转换为一个包含与请求相关的所有信息的独立对象 该转换让你能根据不同的请求将方法参数化 延迟请求执行或将其放入队列中
  • 行为型模式-策略模式

    package per mjn pattern strategy 抽象策略类 public interface Strategy void show package per mjn pattern strategy 具体策略类 用来封装算法
  • 设计模式之(三)---工厂方法模式

    女娲补天的故事大家都听过吧 这个故事是说 女娲在补了天后 下到凡间一看 哇塞 风景太优美了 天空是湛 蓝的 水是清澈的 空气是清新的 太美丽了 然后就待时间长了就有点寂寞了 没有动物 这些看的到 都是静态的东西呀 怎么办 别忘了是神仙呀 没
  • 设计模式——原型模式

    原型模式顾名思义 就是指以某个实例为原型 copy出一个新的实例 该实例属性与原型相同或者是类似 很多时候 我们需要创建大量的相同或者相似的对象 如果一个个用new 构造函数的形式去创建的话比较繁琐 就像孙悟空要想变出成千上万个猴子猴孙总不
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • Java设计模式-装饰者模式Decorator

    介绍 装饰者模式的核心思想是通过创建一个装饰对象 即装饰者 动态扩展目标对象的功能 并且不会改变目标对象的结构 提供了一种比继承更灵活的替代方案 需要注意的是 装饰对象要与目标对象实现相同的接口 或继承相同的抽象类 另外装饰对象需要持有目标
  • [C++]备忘录模式

    备忘录模式 Memento Pattern 保存一个对象的某个状态 以便在适当的时候恢复对象 备忘录模式属于行为型模式 github源码路径 https github com dangwei 90 Design Mode 此文件包含 mai
  • 设计模式——导论

    作为软件开发人员 我们在平时工作的过程中 往往需要编写很多的代码来实现我们的需求 很多的时候会造成代码臃肿和代码冗余的情况 这个时候我们需要引入一个理念 设计模式 设计模式存在的意义在于 1 使得我们的代码更加精炼 2 使我们代码的可读性更
  • 设计模式一之简单工厂模式

    生活示例 刻板印刷 gt 活字印刷举例 喝酒唱歌 人生真爽 gt 对酒当歌 人生几何 可维护 需要修改 则只需要改需要改的字即可 可复用 字体可在后来的印刷复用 可扩展 需要加字 只需要加入相应的刻字即可 灵活性好 字的排列可能竖排或横排
  • linux内核中的设计模式

    创建型 Object Pool Object Pool模式可以提升性能 尤其是在对象的分配 初始化成本高 使用频率高 但使用时间短的情况下 对象池可以设置对象池的大小和回收时间缓存预分配的对象 NT和Linux都有简单的预分配缓存对象的机制
  • 单例模式的八种写法比较

    单例模式是最常用到的设计模式之一 熟悉设计模式的朋友对单例模式都不会陌生 一般介绍单例模式的书籍都会提到 饿汉式 和 懒汉式 这两种实现方式 但是除了这两种方式 本文还会介绍其他几种实现单例的方式 让我们来一起看看吧 简介 单例模式是一种常
  • [C++]外观模式

    外观模式 Facade Pattern 隐藏系统的复杂性 并向客户端提供了一个客户端可以访问系统的接口 这种类型的设计模式属于结构型模式 它向现有的系统添加一个接口 来隐藏系统的复杂性 这种模式涉及到一个单一的类 该类提供了客户端请求的简化
  • 设计模式-享元模式

    一 概念 如果在一个系统中存在多个相同的对象 那么只需要共享一份对象的拷贝 而不必为每一次使用都创建新的对象 目的是提高系统性能 上面的概念乍一听好像单例模式其实不是 单例模式只保存一个对象 但是这里可以有很多个不同对象 但是每个对象只有一
  • 【设计模式】工厂模式(Factory Pattern)

    1 概述 工厂模式 Factory Pattern 是最常用的设计模式之一 它属于创建类型的设计模式 它提供了一种创建对象的最佳方式 在工厂模式中 我们在创建对象时不会对客户端暴露创建逻辑 并且是通过一个共同的接口来指向新创建的对象 工厂模
  • 二十四种设计模式之策略模式

    一 什么是策略模式 简单来说 策略模式是将每一个算法封装到拥有共同接口的不同类中 使得算法可以在不影响客户端的情况下发生变化 也可以理解为可供程序运行时选择的 不同的类 不同的解决方案 策略模式的特点 高内聚低耦合 可扩展 遵循ocp原则
  • 泛型与反射机制在JDBC和Servlet编程中的实践

    写在前面 泛型与反射是java中的两种强大机制 可以很好的提高代码的灵活性和复用性 本篇文章向大家展现在JDBC和Servlet编程场景下反射和泛型技术的实践 通过灵活使用这两种机制打造 高度可复用的JDBC和Servlet代码 1 JDB
  • 设计模式(三)-结构型模式(4)-组合模式

    一 为何需要组合模式 Composite 在代码设计中 有种情况是对象之间存在层次关系 即对象之间会存在父结点和子结点的关系 比如在文件管理系统中 所有文件和文件夹形成树状结构 文件夹目录里存在子文件夹和文件 文件夹属于枝结点 文件属于叶结
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • 2023 年精选:每个 DevOps 团队都应该了解的 5 种微服务设计模式

    微服务彻底改变了应用程序开发世界 将大型整体系统分解为更小 更易于管理的组件 这种架构风格的特点是独立 松散耦合的服务 带来了从可扩展性 模块化到更高的灵活性等众多优势 DevOps 团队如何最好地利用这种方法来实现最高效率 答案在于理解并

随机推荐

  • Leetcode 刷题笔记(四) —— 数组类型解题方法四:模拟

    文章目录 系列文章目录 模拟 54 螺旋矩阵 59 螺旋矩阵 II 总结 系列文章目录 一 数组类型解题方法一 二分法 二 数组类型解题方法二 双指针法 三 数组类型解题方法三 滑动窗口 四 数组类型解题方法四 模拟 五 链表篇之链表的基础
  • pycharm中导入rospy包

    在pycharm中 问题描述 import rospy 显示有错误 在终端中import rospy 能通过 这种问题说明rospy已经安装成功 但是没有导入到pycharm中 解决办法 1 依次点击File gt settings gt
  • qt学习笔记11:QFile文件读写操作、QFileInfo文件信息提取

    QFile文件读写操作 需求 实现一个可以选择文件的对话框 在ui中 分别line edit push button 在widget中水平对齐 再整体和一个TextEdit对齐 界面上就得到一个大概的选取文件的窗口 点击选取文件窗口 左边会
  • PAT Basic 1008. 数组元素循环右移问题 (20)

    一个数组A中存有N N gt 0 个整数 在不允许使用另外数组的前提下 将每个整数循环向右移M M gt 0 个位置 即将A中的数据由 A0A1 AN 1 变换为 AN M AN 1 A0 A1 AN M 1 最后M个数循环移至最前面的M个
  • SLOT专业术语

    slot专业术语 要学习slot的知识首先要了解slot的一些专业术语 下面我们就列举一些slot的专业术语并给大家一一详细说明 现在大多数slot是三行五列的 我们就以三行五列 243lines的slot距离说明各种slot术语 上图出自
  • Wireshark网络抓包工具

    Wireshark工具 1 Wireshark软件简介 2 Wireshark下载 3 Wireshark安装 4 页面介绍 5 常用功能介绍 5 1 网络接口选择 5 2 抓包规则设定 5 3 查找目标数据包 5 4 快速选择过滤数据包
  • TP6的服务在自定义composer包中如何使用

    官方关于Service的说明文档 https www kancloud cn manual thinkphp6 0 1037490 做下概念说明 Service和Provider在TP6中扮演着不同的角色 Service是用于封装特定功能的
  • web 前端学习线路图

    web 前端学习线路图 一 HTML 教程 HTML教程 HTML简介 HTML编辑器 HTML基础 HTML元素 HTML属性 HTML标题 HTML段落 HTML样式 HTML格式化 HTML引用元素 HTML计算机代码元素 HTML注
  • 人工智能学习历程数学篇-概率论(1)

    人工智能学习历程数学篇 概率论 1 概率论基础 随机变量 概率论的一切定义的基础都来源于随机变量 那么何为随机变量呢 所谓的随机变量变量 X 并不代表一个具体的数字 而是一种概率分布 我们可以这样理解随机变量X 当你每次去看随机变量数据的具
  • java stringbuffer 赋值_Java常用类(String, StringBuffer, StringBuilder)

    一 String类 String的实例化方式 通过字面量定义的方式 String str hello world 通过new 构造器的方式 String str new String hello world 面试题 String s new
  • python读取excel某一区域单元格的内容

    sheet1 row values 0 6 10 取第1行 第6 10列 不含第10表 sheet1 col values 0 0 5 取第1列 第0 5行 不含第5行 sheet1 row slice 2 0 2 获取单元格值类型和内容
  • 【链表】循环链表知识点-内含代码基本操作及其说明

    目录 一 概念 二 循环链表基本操作 初始化 头插 插在最前面 尾插 查找数据 获取val的前驱 获得后继 删除数据 删除某位置的值 输出数据 判断plist是否为空链表 没有数据节点 获取plist长度 数据节点的个数 插入数据 获取pl
  • 最短路径算法 迪杰斯特拉、佛洛依德和贝尔曼

    最短路径算法 迪杰斯特拉算法 佛洛依德算法 迪杰斯特拉算法 迪杰斯特拉算法用来解决在有向有权图中某一个点到任意一点的最短路径问题 注意 只能用来解决权为非零的情况 不能够解决权为负数的情况 思想 我是一个搬运工 思想就不讲了 主要是代码 d
  • Vue基础入门---Vue-router

    简介 由于Vue在开发时对路由支持的不足 后来官方补充了vue router插件 它在Vue的生态环境中非常重要 在实际开发中只要编写一个页面就会操作vue router 要学习vue router就要先知道这里的路由是什么 这里的路由并不
  • vps用途

    VPS用途 1 虚拟主机空间 VPS主机非常适合为中小企业 小型门户网站 个人工作室 SOHO一族提供网站空间 较大独享资源 安全可靠的隔离保证了用户对于资源的使用和数据的安全 2 电子商务平台 VPS主机与独立服务器的运行完全相同 中小型
  • STL教程5-STL基本概念及String和vector使用

    活动地址 毕业季 进击的技术er 夏日炎炎 热浪中我们迎来毕业季 这是告别 也是迈向新起点的开始 CSDN诚邀各毕业生 在校生 职场人讲述自己的毕业季故事 分享自己的经验 技术er的进击之路 等你来书写 你可以选择适合自己的对应身份从以下相
  • Calendar根据当前(指定)日期取出指定时间

    以下为亲测 持续更新 一 Calendar根据当前 指定 日期取出本周一本周日和下周一下周日时间 根据Calendar java中定义的DAY OF WEEK来看 Field number for code get code and cod
  • 【LeetCode104】二叉树的最大深度(递归+迭代)

    题目描述 首刷自解 int maxDepth TreeNode root if root nullptr return 0 return max maxDepth root gt left maxDepth root gt right 1
  • k-means算法Python实现--机器学习ML

    k means algorithm 一些概念 partial clustering 每一簇的数据不重叠 至少一簇一个数据 hieraichical clustering 通过构建层次结构来确定聚类分配 density based clust
  • 设计模式-访问者模式

    1 访问者模式被称为最复杂的设计模式 访问者模式访问者模式 Visitor pattern 是一种将数据结构与数据操作分离的设计模式 是指封装一些作用于某种数据结构中的各元素的操作 它可以在不改变数据结构的前提下定义作用于这些元素的新的操作