二十、行为型(访问者模式)

访问者模式(Visitor Pattern)

概念
访问者模式是一种行为型设计模式,允许你在不修改被访问对象的前提下,定义新的操作。它通过将操作封装在访问者类中,从而将操作与对象结构分离。访问者模式非常适合于需要对一组对象进行不同操作的场景。


应用场景

  1. 对象结构稳定:当对象结构相对稳定,但需要为其添加新的操作时,访问者模式可以有效避免修改已有对象的代码。

  2. 复杂的对象结构:在复杂的对象结构中,可能需要对不同的对象执行不同的操作,访问者模式能够简化这些操作的实现。

  3. 需要对对象进行多次操作:当需要对对象进行多种不同操作时,可以使用访问者模式,将每种操作封装在不同的访问者中。

  4. 数据结构遍历:在某些数据结构(如树、图等)的遍历过程中,可以使用访问者模式来处理每个节点的操作。


注意点

  1. 增加新操作的灵活性:访问者模式允许灵活地增加新的操作,但添加新的元素(被访问对象)时,可能需要修改访问者接口,降低了扩展性。

  2. 对象结构的变化:如果对象结构经常变化,使用访问者模式可能会导致维护成本增加,因为每次变化都需要修改访问者的相关代码。

  3. 访问者与被访问者之间的耦合:访问者和被访问者之间的耦合性较强,可能影响到系统的可维护性。


核心要素

  1. Visitor(访问者接口):定义对每种具体元素的访问方法。

  2. ConcreteVisitor(具体访问者):实现访问者接口,定义具体的操作。

  3. Element(元素接口):定义接受访问者的接口。

  4. ConcreteElement(具体元素):实现元素接口,定义具体的被访问者。

  5. ObjectStructure(对象结构):维护一组元素,并提供对元素的遍历。


Java代码完整示例

示例:简单的访问者模式实现

// 访问者接口
interface Visitor {void visit(ConcreteElementA elementA);void visit(ConcreteElementB elementB);
}// 具体访问者
class ConcreteVisitor implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {System.out.println("Visiting ConcreteElementA");}@Overridepublic void visit(ConcreteElementB elementB) {System.out.println("Visiting ConcreteElementB");}
}// 元素接口
interface Element {void accept(Visitor visitor);
}// 具体元素A
class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 具体元素B
class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 对象结构
class ObjectStructure {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 客户端代码
public class VisitorPatternDemo {public static void main(String[] args) {ObjectStructure structure = new ObjectStructure();structure.addElement(new ConcreteElementA());structure.addElement(new ConcreteElementB());ConcreteVisitor visitor = new ConcreteVisitor();structure.accept(visitor);}
}

输出结果

Visiting ConcreteElementA
Visiting ConcreteElementB

各种变形用法完整示例

  1. 多个具体访问者

    通过定义多个具体访问者来实现不同的操作。

    代码示例:多个访问者

    // 另一个具体访问者
    class AnotherVisitor implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {System.out.println("AnotherVisitor visiting ConcreteElementA");}@Overridepublic void visit(ConcreteElementB elementB) {System.out.println("AnotherVisitor visiting ConcreteElementB");}
    }public class MultiVisitorDemo {public static void main(String[] args) {ObjectStructure structure = new ObjectStructure();structure.addElement(new ConcreteElementA());structure.addElement(new ConcreteElementB());ConcreteVisitor visitor1 = new ConcreteVisitor();structure.accept(visitor1); // 使用第一个访问者AnotherVisitor visitor2 = new AnotherVisitor();structure.accept(visitor2); // 使用第二个访问者}
    }
    
  2. 访问者的复杂操作

    访问者可以执行更复杂的操作,比如在访问时修改元素的状态。

    代码示例:复杂操作

    // 具体元素A
    class ConcreteElementA implements Element {private int value;public ConcreteElementA(int value) {this.value = value;}public int getValue() {return value;}public void setValue(int value) {this.value = value;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
    }// 具体访问者:增加值
    class IncrementVisitor implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {int newValue = elementA.getValue() + 1;elementA.setValue(newValue);System.out.println("Incremented ConcreteElementA value to: " + newValue);}@Overridepublic void visit(ConcreteElementB elementB) {// 不做任何操作}
    }public class IncrementVisitorDemo {public static void main(String[] args) {ObjectStructure structure = new ObjectStructure();ConcreteElementA elementA = new ConcreteElementA(10);structure.addElement(elementA);structure.addElement(new ConcreteElementB());IncrementVisitor incrementVisitor = new IncrementVisitor();structure.accept(incrementVisitor); // 增加元素A的值}
    }
    
  3. 遍历复杂对象结构

    对于树形结构等复杂对象,可以使用访问者模式进行遍历和操作。

    代码示例:树形结构

    // 树形元素接口
    interface TreeElement extends Element {List<TreeElement> getChildren();
    }// 具体树形元素
    class TreeNode implements TreeElement {private String name;private List<TreeElement> children = new ArrayList<>();public TreeNode(String name) {this.name = name;}public void addChild(TreeElement child) {children.add(child);}@Overridepublic List<TreeElement> getChildren() {return children;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);for (TreeElement child : children) {child.accept(visitor);}}public String getName() {return name;}
    }// 具体访问者:打印节点名称
    class PrintVisitor implements Visitor {@Overridepublic void visit(ConcreteElementA elementA) {// 不做任何操作}@Overridepublic void visit(ConcreteElementB elementB) {// 不做任何操作}@Overridepublic void visit(TreeNode treeNode) {System.out.println("Visiting TreeNode: " + treeNode.getName());}
    }public class TreeStructureDemo {public static void main(String[] args) {TreeNode root = new TreeNode("Root");TreeNode child1 = new TreeNode("Child 1");TreeNode child2 = new TreeNode("Child 2");root.addChild(child1);root.addChild(child2);child1.addChild(new TreeNode("Child 1.1"));PrintVisitor printVisitor = new PrintVisitor();root.accept(printVisitor); // 遍历树结构}
    }
    

通过这些示例,访问者模式的灵活性和应用场景得以体现,可以根据具体需求实现多种变形用法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57520.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对“一个中心,三重防护”中安全管理中心的理解

安全管理中心 本控制项为网络安全等级保护标准的技术部分。本项主要包括系统管理、审计管理、安全管理和集中管控四个控制点&#xff0c;其中的集中管控可以说是重中之重&#xff0c;主要都是围绕它来展开的。 28448基本要求中安全管理中心 8.1.5 安全管理中心 8.1.5.1 系统…

ELK之路第二步——可视化界面Kibana

Kibana 1.安装2.解压3.修改配置4.启动 这部分内容就比较简单了&#xff0c;水一片文章。 1.安装 需要梯子 官网下载链接&#xff1a;https://www.elastic.co/cn/downloads/past-releases/kibana-7-3-0 如果你去官网下载页面&#xff0c;点击下载是404报错&#xff0c;记得切换…

redis的zset实现下滑滚动分页查询思路

常规zset查询 我们redis的数据为 我们知道 我们常规查询的话 我们假如 zset 表中 有7个元素&#xff0c;然后我们进行分页查询的话&#xff0c;我们一次查3个元素&#xff0c;然后查出来元素 和元素的分数 我们redis的语法应该这样写 zrevrangebyscore wang 1000 0 withsc…

Flutter 12 实现双击屏幕显示点赞爱心多种动画(AnimationIcon)效果

本文主要是使用Flutter封装一个双击屏幕显示点赞爱心UI效果&#xff0c;并实现了爱心Icon 透明度、缩放、旋转、渐变等动画效果。 实现效果&#xff1a; 实现逻辑&#xff1a; 1、封装FavoriteGesture&#xff08;爱心手势&#xff09;实现双击屏幕显示爱心Icon&#xff1b; …

【设计模式系列】抽象工厂模式

一、什么是抽象工厂模式 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一个接口&#xff0c;用于创建一系列相关或相互依赖的对象&#xff0c;而无需指定它们具体的类。这种模式允许客户端使用抽象的接口来创建一组…

VoLTE 微案例:VoLTE 注册失败,I-CSCF 返回 403,HSS(UAR) 返回 5001

目录 1. 问题描述 2. 故障注册流程与正常流程对照 3. 结论 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识(加入 51学通信),或者想要 cpp 方向修改简历,模拟面试,学习指导都可以添加博主低价指导哈。 1. 问题描述

对比迁移项目的改动

文章目录 对比迁移项目的改动场景背景解决方案 对比迁移项目的改动 场景背景 同源定制化项目&#xff0c;同一套代码扩展出来的项目&#xff08;从领导口中得知&#xff09; A项目的有三维地图展示&#xff0c;项目B跑起来却加载不出来&#xff0c;但是本地运行A项目代码&…

Unity性能优化3【内存基础篇】

1.性能、内存管理和垃圾收集的关系 先说结论&#xff0c;内存管理影响着游戏性能&#xff0c;垃圾收集是内存管理的重要部分。 当我们的游戏运行时&#xff0c;它使用内存来存储数据。当不再需要此数据时&#xff0c;存储该数据的内存将被释放&#xff0c;以便可以重复使用。…

vue-pc 实现内嵌式微信扫码登录(附完整代码)

一、准备工作 1. 注册微信开放平台账号 地址&#xff1a;&#xff08;[https://open.weixin.qq.com/](https://open.weixin.qq.com/)&#xff09; 2. 申请开发者资质认证&#xff1a; 3. 创建网站应用 4. 查看应用详情&#xff0c;拿到 AppID 、 AppSecret 和 redirect_uri (授…

如何在服务器上部署开源大模型 GLM-4-9B-Chat 并应用到RAG应用中

本地服务器部署开源大模型有一个前提&#xff0c;就是得有 GPU 显卡资源&#xff0c;在我下面的例子中我租用了 autodl 中的算力资源&#xff0c;具体是租用了一张消费级别的 RTX 3090 显卡。 环境配置 操作系统及版本&#xff1a;ubuntu 22.04CUDA 版本&#xff1a; 12.1pyto…

【MATLAB源码-第263期】基于matlab的帝企鹅优化算法(EPO)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境&#xff1a; MATLAB 2022a 1、算法描述 帝企鹅优化算法&#xff08;Emperor Penguin Optimizer&#xff0c;简称EPO&#xff09;是一种基于自然现象的优化算法&#xff0c;灵感来自于帝企鹅在南极极寒环境中的生活习性。帝企鹅是一种群居动物&#xff0c;生活在极端…

再创佳绩 | 竹云荣获“数据要素×”大赛黑龙江分赛一等奖!

近日&#xff0c;由国家数据局、黑龙江省人民政府指导&#xff0c;黑龙江省发改委、黑龙江省数据局主办的2024年“数据要素”大赛黑龙江分赛决赛盛大召开。竹云作为联合单位参与《供热数据资产登记评价中心供热数据要素综合服务平台》项目&#xff0c;荣获绿色低碳赛道一等奖。…

C++ [项目] 愤怒的小鸟

现在才发现C游戏的支持率这么高&#xff0c;那就发几篇吧 零、前情提要 此篇为 制作,由于他没有CSDN,于是由我代发 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有的自己猜,如果你很固执……私我吧 …

java-实例化一个List,然后添加数据的方法详解

在Java中&#xff0c;实例化一个 List 并向其中添加数据非常简单。List 是一个接口&#xff0c;因此我们通常使用它的常见实现类 ArrayList 或 LinkedList。以下是一些常见的操作方法&#xff1a; ### 1. 使用 ArrayList 实例化并添加数据 java import java.util.ArrayList; …

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态&#xff1a;应用的多个实例必须按照某种顺序启动&#xff0c;并且必须成组存在&#xff0c;例如一个应用中必须存在一个A Pod和两个B Pod&#xff0c;且A Pod必须先于B Pod启动的场景 存储状态&#xff1a;应用存在多个实例&…

分享Vue3中的一个路由加载函数,基于Glob导入模式,根据路径自动生成路由

哈喽&#xff0c;大家好&#xff01;我是「励志前端小黑哥」&#xff0c;我带着最新发布的文章又来了&#xff01; 专注前端领域10年&#xff0c;专门分享那些没用的前端知识&#xff01; 今天要分享的内容&#xff0c;是一段路由加载的函数代码&#xff0c;这段代码能自动读取…

StringBulider和StringBuffer的底层源码剖析

要深入了解 StringBuffer 和 StringBuilder 的区别&#xff0c;从底层源码的角度来解析&#xff0c;包括它们的创建、扩容机制等&#xff0c;可以参考 JDK 1.8 的源码。 1. AbstractStringBuilder 类 StringBuffer 和 StringBuilder 都继承自 AbstractStringBuilder。…

Three.js实现小米 su7 压缩后的模型加载

Three.js实现小米 su7 压缩后的模型加载 预览&#xff1a; https://threehub.cn/#/codeMirror?navigationThreeJS&classifybasic&idgltfOptLoader import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js impo…

复旦大学全球供应链研究中心揭牌,合合信息共话大数据赋能

10月13日&#xff0c;复旦大学全球供应链研究中心&#xff08;以下简称“中心”&#xff09;揭牌仪式在复旦大学管理学院政立院区隆重举行。我国的供应链体系庞大复杂&#xff0c;在百年未有之大变局下&#xff0c;保障产业链供应链安全已成为我国的重要战略目标。中心的设立旨…

《Vue3 版本差异》Vue3.5+ 在组件或HTML元素绑定 ref 差异

组件上的 ref&#xff0c;组合式写法的变化&#xff1b; 在 2024.09.03 发布的 v3.5.0 版上新增接口 useTemplateRef&#xff1b; v3.5 之前 代码第 8 行&#xff0c;导入 ref&#xff1b;代码第 10 行&#xff0c;使用 ref 传参为 null&#xff0c;变量名与 第三行 ref 同…