【设计模式】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:支持驳回后自动跨节点跳回

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

Hadoop阶段性技能抽检题,无直接答案但有提示信息

项目名:Hadoop平台及组件的部署管理 考核内容: 考核以大数据技术为核心内容,重点考查同学们基于Hadoop平台环境下,利用Hadoop技术生态组件,综合软件开发相关技术,解决实际问题的能力,所有学生在…

LeetCode hot100-38-Y

226. 翻转二叉树给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。这道题莫名其妙做出来了,看评论好多人都是莫名其妙做出来的。就是连续做了几道题有感觉了。很难解释。 我的做法 后序递归 class Solution {public TreeNode i…

LeetCode:2589.完成所有任务的最少时间(贪心 Java)

目录 完成所有任务的最少时间 题目描述: 实现代码与解析: 贪心 原理思路: 完成所有任务的最少时间 题目描述: 你有一台电脑,它可以 同时 运行无数个任务。给你一个二维整数数组 tasks ,其中 tasks[i] …

Linux 系统下进程异常的处理方式

Linux 系统异常进程处理 一、僵尸进程 说明:僵尸进程对系统来说就是系统已经接管不了并处于异常状态的进程,既不会自动释放,也不能被系统接管,下面列出几种查看并kill僵尸进程的方式 。 方式一、使用如下命令查看目前系统状态为…

【C语言】水仙花数

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

【C++】---继承

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

Promise链式调用与错误处理

Promise链式调用是一种处理异步操作的方法,它可以依次执行多个异步任务,并且可以在每个任务完成后进行后续操作。 在Promise链式调用中,每个任务都返回一个Promise对象,可以通过调用.then()方法来指定任务完成后的操作&#xff0…

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

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

MYSQL库管理---1.默认系统库 2.创建/删除/查看库

文章目录 @[TOC](文章目录)MYSQL默认的系统库1、information_schema(数据库)2、mysql3、performance_schema (性能库)4、sysMYSQL创建/删除/查看库MYSQL默认的系统库 1、information_schema(数据库) 1、记录了用户、表、视图等元数据信息。这个库是虚拟出来的库,是由MySQL…

信息流中的混排与流控

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

Python---Pandas万字总结(2)

DataFrame深度学习 使用 pandas 做数据分析,那么DataFrame一定是被使用得最多的类型,它可以用来保存和处理异质的二维数据。这里所谓的“异质”是指DataFrame中每个列的数据类型不需要相同,这也是它区别于 NumPy 二维数组的地方。DataFrame提…

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

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

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

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

每日新闻掌握【2024年5月13日 星期一】

2024年5月13日 星期一 农历四月初六 TOP大新闻 全国23个城市全面取消限购,超50城支持住房“以旧换新” 据统计,截至5月9日,全国共计50余个城市对限购政策松绑,其中西安、成都、杭州、佛山、东莞、厦门、南京、苏州等23个城市全面…

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…