【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)

🔍目的


允许将新功能添加到现有的类层次结构中,而不会影响这些层次结构,也不会有四人帮访客模式中那样循环依赖的问题。

🔍解释

真实世界例子

我们有一个调制解调器类的层次结构。 需要使用基于过滤条件的外部算法(是Unix或DOS兼容的调制解调器)来访问此层次结构中的调制解调器。

通俗描述

非循环访问者允许将功能添加到现有的类层次结构中,而无需修改层次结构

维基百科

非循环访客模式允许将新功能添加到现有的类层次结构中,而不会影响这些层次结构,也不会创建四人帮访客模式中固有的循环依赖问题。

程序示例

调制解调器的层次结构:

public abstract class Modem {public abstract void accept(ModemVisitor modemVisitor);
}public class Zoom extends Modem {...@Overridepublic void accept(ModemVisitor modemVisitor) {if (modemVisitor instanceof ZoomVisitor) {((ZoomVisitor) modemVisitor).visit(this);} else {LOGGER.info("Only ZoomVisitor is allowed to visit Zoom modem");}}
}public class Hayes extends Modem {...@Overridepublic void accept(ModemVisitor modemVisitor) {if (modemVisitor instanceof HayesVisitor) {((HayesVisitor) modemVisitor).visit(this);} else {LOGGER.info("Only HayesVisitor is allowed to visit Hayes modem");}}
}

调制解调器访问者类结构:

public interface ModemVisitor {
}public interface HayesVisitor extends ModemVisitor {void visit(Hayes hayes);
}public interface ZoomVisitor extends ModemVisitor {void visit(Zoom zoom);
}public interface AllModemVisitor extends ZoomVisitor, HayesVisitor {
}public class ConfigureForDosVisitor implements AllModemVisitor {...@Overridepublic void visit(Hayes hayes) {LOGGER.info(hayes + " used with Dos configurator.");}@Overridepublic void visit(Zoom zoom) {LOGGER.info(zoom + " used with Dos configurator.");}
}public class ConfigureForUnixVisitor implements ZoomVisitor {...@Overridepublic void visit(Zoom zoom) {LOGGER.info(zoom + " used with Unix configurator.");}
}

代码实践

    var conUnix = new ConfigureForUnixVisitor();var conDos = new ConfigureForDosVisitor();var zoom = new Zoom();var hayes = new Hayes();hayes.accept(conDos);zoom.accept(conDos);hayes.accept(conUnix);zoom.accept(conUnix);   

程序输出:

 

    // Hayes modem used with Dos configurator.// Zoom modem used with Dos configurator.// Only HayesVisitor is allowed to visit Hayes modem// Zoom modem used with Unix configurator.

🔍类图

Acyclic Visitor 

🔍适用场景

  • 需要在现有层次结构中添加新功能而无需更改或影响该层次结构时。
  • 当某些功能在层次结构上运行,但不属于层次结构本身时。 例如 ConfigureForDOS / ConfigureForUnix / ConfigureForX问题。
  • 当您需要根据对象的类型对对象执行非常不同的操作时。
  • 当访问的类层次结构将经常使用元素类的新派生进行扩展时。
  • 当重新编译,重新链接,重新测试或重新分发派生元素非常昂贵时。

🔍结论

好处:

  • 类层次结构之间没有依赖关系循环。
  • 如果添加了新访客,则无需重新编译所有访客。
  • 如果类层次结构具有新成员,则不会导致现有访问者中的编译失败。

坏处:

  • 通过证明它可以接受所有访客,但实际上仅对特定访客感兴趣,从而违反Liskov的替代原则
  • 必须为可访问的类层次结构中的所有成员创建访问者的并行层次结构。

🔍扩展:

 Liskov的替代原则

1.子类必须保留父类的行为

  子类应该继承并保持父类的所有属性和方法,以确保它们在同样的上下文中能够正常工作。

2.子类可以扩展父类的行为

  子类可以在不破坏父类原有行为的前提下,添加新的方法或属性来扩展功能。

3.子类覆盖父类方法时遵循约定

  如果子类需要覆盖(重写)父类的方法,那么子类的方法参数、返回类型和异常处理等要与父类方法保持一致,以确保可以无缝替换。

4.避免破坏类的不变性

  如果父类拥有某些不变性质或约束,子类也应当遵守这些约束,不应该破坏这些约定。

遵循里氏替换原则有助于构建更健壮、灵活且易于维护的代码。如果违反了这一原则,可能会导致意外的行为,使代码变得不稳定或难以理解。通过正确地应用里氏替换原则,可以确保你的代码在继承体系中保持稳定和一致。 


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

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

相关文章

奖金+1 万,OpenTenBase 开源核心贡献挑战赛,KB 专家助力其跑在 K8s 上

OpenTenBase 是由开放原子开源基金会孵化及运营的开源项目,是一款开放中立的企业级分布式 HTAP 开源数据库。OpenTenBase 具备高扩展性、商业数据库语法兼容、分布式 HTAP 引擎、多级容灾和多维度资源隔离等能力,已成功应用于金融、医疗、航天等行业的核…

FlyFlow:支持驳回后自动跨节点跳回

本周更新 新增:审批节点驳回(拒绝配置的驳回)支持自动跳回当前节点新增:修改数据节点新增:删除数据节点新增:子流程支持配置自动跳过发起人节点优化:两个项目合并一个单体项目优化:…

【C语言】水仙花数

问题 水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数或阿姆斯壮数数(Armstrong number)。 它是指一个n位数(n≥3)…

【C++】---继承

【C】---继承 一、继承的概念及定义1、继承的概念2、定义语法格式3、继承基类成员访问方式的变化 二、基类 和 派生类 的对象之间的赋值转换1、赋值规则2、切片(1)子类对象 赋值 给 父类对象(2)子类对象 赋值 给 父类指针&#xf…

Python邮件处理库之flanker使用详解

概要 Flanker是一个开源的邮件处理库,专门设计用于解析、验证和构建电子邮件地址和MIME消息。由Mailgun开发,它旨在提高邮件处理的效率和准确性,尤其适用于需要高效邮件验证和解析的应用程序。 安装 安装Flanker非常简单,可以通过Python的包管理器pip进行安装: pip ins…

信息流中的混排与流控

待完成. 一. 背景 问题特点: 无法事先拿到所有请求, 离线统一求解. 因此叫 online-matching.应用于在线服务, 求解rt不能高于50ms 二. CIKM 22’, 阿里广告动态定坑 见参考[1]. 2.1 问题建模,动态背包 略, 详见论文 2.2 求解, pidbeam search 思考: beam search 有用的…

使用 cloudflare 免费服务,搭建临时邮箱,无需暴露自己的真实邮箱地址,保护个人隐私

使用 cloudflare 免费服务,搭建临时邮箱 地址 在线演示 🌐Github地址 https://github.com/find-xposed-magisk/cloudflare_temp_email 功能/TODO Cloudflare D1 作为数据库 使用 Cloudflare Pages 部署前端 使用 Cloudflare Workers 部署后端 email 转…

【源码+文档+调试讲解】微信小程序家政项目小程序

摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序家政项目小程序的开发全过程。通过分析微信小程序家政项目小程序管理的不足,创建了一个计算机管理微信小程序家政项目小程序的方案。文章介…

STM32睡眠模式

文章目录 前言PWR介绍电源框图上电复位和掉电复位可编程电压检测器低功耗模式模式选择电源控制寄存器 睡眠模式停止模式待机模式 前言 在单片机产品中,例如遥控这类产品,长时间处于待机状态下,所以对于这类产品在待机时就应该尽可能的减少不…

【环境安装】nodejs 国内源下载与安装以及 npm 国内源配置

前言 Node.js 是一个基于 Chrome V8 引擎构建的 JavaScript 运行时环境,它能够使 JavaScript 在服务器端运行。它拥有强大的包管理器 npm,使开发者能够轻松管理和共享 JavaScript 代码包。 在中国,由于众所周知的原因,我们可能会…

JavaScript基础(七)

isNaN //用来判断一个变量是不是一个非数字 不是来判断是不是number类型&#xff0c;而是判断当前值能不能转为number类型&#xff0c;OK&#xff1f;懂了。 还有同学不明白&#xff0c;来看实例: <script> //isNaN(非数字)→true &#xff08;数字&#xff09;→fal…

Qt qt5.3集成mqtt模块

参考 【Qt官方MQTT库的使用&#xff0c;附一个MqttClient例子】 - 叶小鹏 - 博客园 (cnblogs.com)MQTT&#xff1a;windows最简单搭建mqtt服务端及本地客户端测试_emqx-windows-4.3.6-CSDN博客MQTTX 下载 编译 我从Github下载的是Release v5.12.5 qt/qtmqtt (github.com)版…

单链表题-ysf-反转-中间节点-回文-合并-分割

环形链表的约瑟夫问题_牛客题霸_牛客网 经典的约瑟夫环 #include <stdint.h> #include <stdlib.h> //创建链表 typedef struct ListNode ListNode;ListNode* buyNode(int x){ListNode* newNode(ListNode*)malloc(sizeof(ListNode));if(newNodeNULL){exit(1);}newN…

C++ C# 贝塞尔曲线

二阶贝塞尔曲线公式 三阶贝塞尔曲线公式 C 三维坐标点 二阶到N阶源码 //二阶公式&#xff1a; FVector BezierUtils::CalculateBezierPoint(float t, FVector startPoint, FVector controlPoint, FVector endPoint) {float t1 (1 - t) * (1 - t);float t2 2 * t * (1 - t);…

关于JVM内存模型和堆内存模型的理解

文章目录 前言一、JVM 内存模型的理解1.第一部分&#xff1a;线程共享区&#xff08;堆和方法区&#xff09;2.第二部分&#xff1a;线程独占区&#xff08;程序计数器、虚拟机栈和本地方法栈&#xff09;3.JVM的几个知识点3.1 垃圾回收就指线程共享区&#xff08;堆和方法区&a…

python数据分析——数据可视化(图形绘制基础)

数据可视化&#xff08;图形绘制基础&#xff09; 前言一、图形绘制基础Matplotlib简介使用过程sin函数示例 二、常用图形绘制折线图的绘制plot示例 散点图的绘制plot示例 柱状图的绘制bar示例 箱型图绘制plot.box示例 饼状图的绘制pie示例 三、图形绘制的组合情况多个折线图的…

MacOS docker 安装与配置

orbstack 安装 官网&#xff1a; https://orbstack.dev 下载链接&#xff1a;Download OrbStack Fast, light, simple Docker Desktop alternative 选择是Apple M系列处理器&#xff0c; 或 Intel系列处理器 到这里就安装好了Orbstack软件&#xff0c;下面开始配置docker 下…

Python-VBA函数之旅-vars函数

目录 一、vars函数的常见应用场景 二、vars函数使用注意事项 三、如何用好vars函数&#xff1f; 1、vars函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;https://myelsa1024.blog.csdn.net/ 一、vars函数…

MySQL旧表做分区流程

1. 为什么做分区 数据库分区是将数据库中的数据划分成独立的部分&#xff0c;每个部分称为一个分区。分区可以根据特定的标准&#xff0c;如范围、列表或哈希值&#xff0c;将数据分隔到不同的物理存储位置中。数据库表分区可以在多种情况下提供显著的好处。以下是一些应该考虑…