24 行为型模式-访问者模式

news/2024/5/5 10:55:08/文章来源:https://blog.csdn.net/weixin_39563769/article/details/134084137
1 访问者模式介绍

访问者模式在实际开发中使用的非常少,因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差,可维护性变差,在没有特别必要的情况下,不建议使用访问者模式。
在这里插入图片描述

2 访问者模式原理

在这里插入图片描述
在这里插入图片描述

3 访问者模式实现

我们以超市购物为例,假设超市中的三类商品: 水果,糖果,酒水进行售卖. 我们可以忽略每种商品的计价方法,因为最终结账时由收银员统一集中处理,在商品类中添加计价方法是不合理的设计.我们先来定义糖果类和酒类、水果类.

/*** 抽象商品父类**/
public abstract class Product {private String name; //商品名private LocalDate produceDate; //生产日期private double price; //商品价格public Product(String name, LocalDate produceDate, double price) {this.name = name;this.produceDate = produceDate;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public LocalDate getProduceDate() {return produceDate;}public void setProduceDate(LocalDate produceDate) {this.produceDate = produceDate;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}
/*** 糖果类**/
public class Candy extends Product implements Acceptable{public Candy(String name, LocalDate produceDate, double price) {super(name, produceDate, price);}@Overridepublic void accept(Visitor visitor) {//在accept方法中调用访问者, 并将自己 this 传递回去.visitor.visit(this);}
}
/*** 酒水类**/
public class Wine extends Product implements Acceptable{public Wine(String name, LocalDate produceDate, double price) {super(name, produceDate, price);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}
/*** 水果类**/
public class Fruit extends Product implements Acceptable{private double weight;  //重量public Fruit(String name, LocalDate produceDate, double price, double weight) {super(name, produceDate, price);this.weight = weight;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}
访问者接口

收银员就类似于访问者,访问用户选择的商品,我们假设根据生产日期进行打折,过期商品不能够出售. 注意这种计价策略不适用于酒类,作为收银员要对不同商品应用不同的计价方法。

/*** 访问者接口 - 根据入参的不同调用对应的重载方法**/
public interface Visitor {public void visit(Candy candy); //糖果重载方法public void visit(Wine wine); //酒类重载方法public void visit(Fruit fruit); //水果重载方法
}
具体访问者

创建计价业务类,对三类商品进行折扣计价,折扣计价访问者的三个重载方法分别实现了3类商品的计价方法,体现了visit() 方法的多态性.

/*** 折扣计价访问者类**/
public class DiscountVisitor implements Visitor {private LocalDate billDate;public DiscountVisitor(LocalDate billDate) {this.billDate = billDate;System.out.println("结算日期: " + billDate);}@Overridepublic void visit(Candy candy) {System.out.println("糖果: " + candy.getName());//糖果大于180天,禁止售卖,否则糖果一律九折long days = billDate.toEpochDay() - candy.getProduceDate().toEpochDay();if(days > 180){System.out.println("超过半年的糖果,请勿食用!");}else{double realPrice = candy.getPrice() * 0.9;System.out.println("糖果打折后的价格为: " +NumberFormat.getCurrencyInstance().format(realPrice));}}@Overridepublic void visit(Wine wine) {System.out.println("酒类: " + wine.getName() +",无折扣价格!");System.out.println("原价售卖: " +NumberFormat.getCurrencyInstance().format(wine.getPrice()));}@Overridepublic void visit(Fruit fruit) {System.out.println("水果: " + fruit.getName());long days = billDate.toEpochDay() - fruit.getProduceDate().toEpochDay();double rate = 0;if(days > 7){System.out.println("超过七天的水果,请勿食用!");}else if(days > 3){rate = 0.5;}else{rate = 1;}double realPrice = fruit.getPrice() * fruit.getWeight() * rate;System.out.println("水果价格为: " +NumberFormat.getCurrencyInstance().format(realPrice));}
}
public class Client {public static void main(String[] args) {//        Candy candy = new Candy("德芙巧克力", LocalDate.of(2022, 1, 1), 10.0);
//
//        Visitor visitor = new DiscountVisitor(LocalDate.of(2022,10,5));
//        visitor.visit(candy);//将3件商品加入购物车
//        List<Product> products = Arrays.asList(
//                new Candy("金丝猴奶糖",LocalDate.of(2022,10,1),10),
//                new Wine("郎酒",LocalDate.of(2022,10,1),1000),
//                new Fruit("草莓",LocalDate.of(2022,10,8),50,1)
//                );//        Visitor visitor = new DiscountVisitor(LocalDate.of(2022,10,5));
//        for (Product product : products) {
//            //visitor.visit();
//        }//模拟添加多个商品List<Acceptable> list = Arrays.asList(new Candy("金丝猴奶糖",LocalDate.of(2022,10,1),10),new Wine("郎酒",LocalDate.of(2022,10,1),1000),new Fruit("草莓",LocalDate.of(2022,10,8),50,1));Visitor visitor = new DiscountVisitor(LocalDate.of(2022,10,11));for (Acceptable product : list) {product.accept(visitor);}}
}

上面的代码虽然可以完成当前的需求,但是设想一下这样一个场景: 由于访问者的重载方法只能对当个的具体商品进行计价,如果顾客选择了多件商品来结账时,就可能会引起重载方法的派发问题(到底该由谁来计算的问题).

首先我们定义一个接待访问者的类 Acceptable,其中定义了一个accept(Visitor visitor)方法, 只要是visitor的子类都可以接收.

/*** 接待者这接口 (抽象元素角色)**/
public interface Acceptable {//接收所有的Visitor访问者的子类public void accept(Visitor visitor);
}
/**
* 糖果类
* @author spikeCong
* @date 2022/10/18
**/
public class Candy extends Product implements Acceptable{public Candy(String name, LocalDate producedDate,double price) {super(name, producedDate, price);}//测试@Overridepublic void accept(Visitor visitor) {//accept实现方法中调用访问者并将自己 "this" 传回。this是一个明确的身份,不存在任何泛型visitor.visit(this);}
}

代码编写到此出,就可以应对计价方式或者业务逻辑的变化了,访问者模式成功地将数据资源(需实现接待者接口)与数据算法 (需实现访问者接口)分离开来。重载方法的使用让多样化的算法自成体系,多态化的访问者接口保证了系
统算法的可扩展性,数据则保持相对固定,最终形成⼀个算法类对应⼀套数据。

4 访问者模式总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

预制件二维码怎么做

凡尔码的二维码管理系统不仅提供了高效便捷的二维码生成功能&#xff0c;还配备了一套完善的预制构件管理方案。通过扫描二维码&#xff0c;用户可以查看预制构件的详细信息&#xff0c;包括项目名称、构建名称、安装位置、重量、生产日期、生产单位、产品出厂检验材料、尺寸等…

【算法-数组2】有序数组的平方 和 长度最小的子数组

今天&#xff0c;带来数组相关算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输…

React-快速搭建开发环境

1.安装 说明&#xff1a;react-excise-01是创建的文件名 npx create-react-app react-excise-01 2. 打开文件 说明:we suggest that you begin by typing:下面即是步骤。 cd react-excise-01 npm start 3.显示

ip划分与私公网ip、ip的传递

报文问路&#xff1a;1、不知道跳转默认路由器&#xff0c;2、知道路径&#xff0c;向对应路径发出报文&#xff0c;3、路口路由器&#xff0c;下一步就是目标主机在哪。 想要通信必须同在一个局域网&#xff0c;其实将公网就可以看作一个大型的局域网。 在同一个局域网内发送…

MySQL扩展语句和约束条件

MySQL扩展语句 create TABLE if not exists ky32 (id int(4) zerofill primary key auto_inc rement&#xff0c; #表示该字段可以自增长&#xff0c;默认从1开始每条记录会自动递增1name varchar(10) not null,cradid int(10) not null unique key,hobby varchar (50))&#x…

Android NDK开发详解之Application.mk探秘

Android NDK开发详解之Application.mk探秘 概览变量APP_ASFLAGSAPP_ASMFLAGSAPP_BUILD_SCRIPTAPP_CFLAGSAPP_CLANG_TIDYAPP_CLANG_TIDY_FLAGSAPP_CONLYFLAGSAPP_CPPFLAGSAPP_CXXFLAGSAPP_DEBUGAPP_LDFLAGSAPP_MANIFESTAPP_MODULESAPP_OPTIMAPP_PLATFORMAPP_PROJECT_PATHAPP_STL…

矢量图形编辑软件illustrator 2023 mac中文软件特点

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator 2023 mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软…

一文了解什么是JWT 与sessions

​session 和 JSON Web 令牌 (JWT) 是在调用之间维护此身份验证状态的两种最流行的方法。两者各有利弊&#xff0c;在它们之间进行选择需要了解这些权衡以及它们与应用程序的特定需求之间的关系。 一、基于session的身份验证 在基于session的身份验证&#xff08;也称为基于 c…

spring boot配置ssl(多cer格式)保姆级教程

1. 准备cer格式的证书&#xff1b; 2. 合并cer证书并转化成jks格式的证书 为啥有这一步&#xff0c;因为cer证书配置在spring boot项目中&#xff0c;项目启动不起来。如果有大佬想指导一下可以给我留言&#xff0c;在此先谢过大佬。 1&#xff09;先创建一个jks格式的证…

【WSL 2】Windows10 安装 WSL 2,并配合 Windows Terminal 和 VSCode 使用

【WSL 2】Windows10 安装 WSL 2&#xff0c;并配合 Windows Terminal 和 VSCode 使用 1 安装 Windows Terminal2 安装 WSL 23 在 Windows 文件资源管理器中打开 WSL 项目4 在 VSCode 中使用 WSL 24.1 必要准备4.2 从 VSCode 中 Connect WSL4.3 从 Linux 中打开 VSCode 1 安装 W…

分布式:一文吃透分布式事务和seata事务

目录 一、事务基础概念二、分布式事务概念什么是分布式事务分布式事务场景CAP定理CAP理论理解CAPCAP的应用 BASE定理强一致性和最终一致性BASE理论 分布式事务分类刚性事务柔性事务 三、分布式事务解决方案方案汇总XA规范方案1&#xff1a;2PC第一阶段&#xff1a;准备阶段第二…

基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类 计算机竞赛

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

基于SpringBoot的社区医院管理系统设计与实现

目录 前言 一、技术栈 二、系统功能介绍 管理员功能实现 用户信息管理 病例信息管理 家庭医生管理 药品信息管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的…

pgAdmin 4 v7.8 发布,PostgreSQL 开源图形化管理工具

导读pgAdmin 是 PostgreSQL 领先的开源图形化管理工具。pgAdmin 4 旨在满足新手和有经验的 Postgres 用户的需求&#xff0c;提供强大的图形界面&#xff0c;简化了数据库对象的创建、维护和使用。 pgAdmin 开发团队日前发布了 pgAdmin 4 v7.8 版本&#xff0c;这个版本包括 21…

GPT的广泛应用会对互联网公司造成挑战吗?——探讨GPT在实际使用中的应用和影响

文章目录 前言GPT 技术的背景和发展历程GPT 技术对互联网行业的影响GPT 技术在互联网行业中的应用GPT 技术对于用户隐私和数据安全的威胁GPT 技术对于人类工作岗位的影响加强 AI 伦理和监管加强 AI 安全性和隐私保护推动 AI 创新和发展&#xff0c;避免过度依赖 AIGPT 技术是一…

在重生奇迹MU中如何选择最佳的挂机点?

如何寻找最适合自己的挂机地点呢&#xff1f;小编建议玩家朋友从以下几点着手加以抉择。 怪物的等级不能过高 你的最佳挂机点要结合自己的实际情况来定&#xff0c;如果你刷怪比较吃力的话&#xff0c;那么此游戏地图并不适合你挂机&#xff0c;一旦挂机过程中&#xff0c;你…

FIFO基础知识

&#x1f380; 文章作者&#xff1a;二土电子 &#x1f338; 关注文末公众号获取其他资料和工程文件&#xff01; &#x1f438; 期待大家一起学习交流&#xff01; 文章目录 一、FIFO简介1.1 什么是FIFO1.2 FIFO的功能1.3 什么时候使用FIFO1.4 FIFO的分类1.5 FIFO重要参数 …

大厂面试题-JVM为什么使用元空间替换了永久代?

目录 面试解析 问题答案 面试解析 我们都知道Java8以及以后的版本中&#xff0c;JVM运行时数据区的结构都在慢慢调整和优化。但实际上这些变化&#xff0c;对于业务开发的小伙伴来说&#xff0c;没有任何影响。 因此我可以说&#xff0c;99%的人都回答不出这个问题。 但是…

中科驭数受邀亮相两场重要行业盛会,摘得2023“璀璨技术奖”奖项

近日&#xff0c;中科驭数作为DPU算力基础设施领军企业&#xff0c;受邀参与2023信息技术应用创新专题研讨会暨第二届集成电路产业发展创新大会、以及2023AI网络创新大会。在两大行业盛会上&#xff0c;中科驭数与行业知名专家和企业代表齐聚一堂&#xff0c;分享了DPU在集成电…