20【访问者设计模式】

news/2024/5/17 17:14:49/文章来源:https://blog.csdn.net/Bb15070047748/article/details/127095725

文章目录

  • 二十、访问者设计模式
    • 20.1 访问者设计模式简介
      • 20.1.1 访问者设计模式概述
      • 20.1.2 访问者设计模式的UML类图
    • 20.2 访问者设计模式的实现
    • 20.3 访问者设计模式的优缺点


二十、访问者设计模式

20.1 访问者设计模式简介

20.1.1 访问者设计模式概述

访问者设计模式(Visitor Pattern):是一种将数据结构与数据操作分离的设计模式,该模式封装一些作用于操作其内部的数据的步骤,可以在不改变数据结构的前提下定义作用于这些元素的新操作

生活中的访问者模式场景也非常多;

如:一个家庭中有非常多的成员,如孩子、父亲、母亲等;这些家庭成员都有非常多的一些属性/行为,作为访问者的我们(丈夫、妻子)都可以去对家庭成员的信息进行访问,但是不同的角色访问的感兴趣的内容是不一样的;例如丈夫关心孩子的兴趣爱好、平时的生活信息,关心父母的饮食、社会生活等;而妻子则关心孩子的身高体重、饮食爱好,关心父母的饮食习惯、起居生活等;

可见不同的访问者,对同一类事物所关注点是不一样的;下面我们将使用访问者设计模式来实现这一案例;

20.1.2 访问者设计模式的UML类图

访问者模式主要有5个角色:

  • 1)抽象元素(Element):定义了一个接受访问者的方法(accept),表示所有的元素都要可以被访问者访问。
  • 2)具体元素(ConcreteElement): 提供接受访问方法(accpet)的具体实现,通常情况下是使用访问者提供的访问该元素类的方法:visitor.visit(this)
  • 3)抽象访问者(Visitor):定义了对每一个元素(Element)访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数(Element的实现类个数)是一样的,因为要保证访问者能够访问所有的元素。因此,访问者模式要求元素类的个数不能经常变动。
  • 4)具体访问者(ConcreteVisitor):提供访问者的具体实现。
  • 5)对象结构(Object Structure):维护元素集合,并提供方法接受访问者对这些元素操作。

在这里插入图片描述

20.2 访问者设计模式的实现

我们前面举了一个家庭的案例,在上述案例中;我们根据UML类图来找到对应的角色:

  • 孩子、父母:属于具体元素,具备很多的属性和行为,就是访问者模式中提到的数据结构
  • 丈夫、妻子:属于具体访问者,用于访问孩子、父母的属性和行为,就是访问者模式中提到的数据操作

接下来我们使用代码来实现刚刚描述的场景;

  • 1)定义抽象元素:
package com.pattern.demo01;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author lscl* @version 1.0* @intro: 家人类,接受其他人的访问(抽象元素)*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class IFamily {private String name;private Integer age;// 基本信息public abstract void basic();// 饮食信息public abstract void diet();// 生活信息public abstract void live();public abstract void accept(IVisitor visitor);
}
  • 2)定义具体元素(孩子):
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro: 孩子类(具体的元素)*/
public class ChildFamily extends IFamily {public ChildFamily(String name, Integer age) {super(name, age);}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}// 基本信息public void basic() {System.out.println("【" + getName() + "】的身高:【170】");System.out.println("【" + getName() + "】的体重:【65KG】");System.out.println("-------------------");}// 饮食信息public void diet() {System.out.println("【" + getName() + "】喜欢吃红烧肉");System.out.println("【" + getName() + "】喜欢喝可乐");System.out.println("-------------------");}// 生活信息public void live() {System.out.println("【" + getName() + "】平时喜欢跟小红在一起玩");System.out.println("【" + getName() + "】晚上8.30喜欢看少儿频道");System.out.println("-------------------");}
}
  • 3)定义具体元素(父母):
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro: 父母类(具体的元素)*/
public class ParentFamily extends IFamily {public ParentFamily(String name, Integer age) {super(name, age);}// 基本信息public void basic() {System.out.println("【" + getName() + "】身高:【162】");System.out.println("【" + getName() + "】体重:【48kg】");System.out.println("-------------------");}// 饮食信息public void diet() {System.out.println("【" + getName() + "】喜欢吃青菜");System.out.println("【" + getName() + "】喜欢喝茶");System.out.println("-------------------");}// 生活信息public void live() {System.out.println("【" + getName() + "】平时喜欢跟隔壁老王下棋");System.out.println("【" + getName() + "】晚上7.30喜欢看新闻联播");System.out.println("-------------------");}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}
}
  • 4)定义抽象访问者:
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro: 抽象访问者*/
public interface IVisitor {// 用于访问孩子的信息public void visit(ChildFamily childFamily);// 用于访问父母的信息public void visit(ParentFamily parentFamily);
}
  • 5)定义具体访问者(丈夫):
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro: 爸爸访问者(具体访问者)*/
public class FatherVisitor implements IVisitor {@Overridepublic void visit(ChildFamily childFamily) {// 爸爸关心孩子的基本信息、生活等...childFamily.basic();childFamily.live();}@Overridepublic void visit(ParentFamily parentFamily) {// 爸爸关心父母的基本信息、饮食、生活等parentFamily.basic();parentFamily.diet();parentFamily.live();}
}
  • 6)定义具体访问者(妻子):
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro: 妈妈访问者(具体访问者)*/
public class MotherVisitor implements IVisitor {@Overridepublic void visit(ChildFamily childFamily) {// 妈妈关心孩子的基本信息、饮食等...childFamily.basic();childFamily.diet();}@Overridepublic void visit(ParentFamily parentFamily) {// 妈妈关心父母的饮食、生活等parentFamily.diet();parentFamily.live();}
}
  • 7)结构对象:
package com.pattern.demo01;import java.util.ArrayList;
import java.util.List;/*** @author lscl* @version 1.0* @intro: 结构对象: 提供方法接受访问者对该集合所有元素的操作*/
public class ObjectStructure {private List<IFamily> families=new ArrayList<>();// 添加元素public void addElement(IFamily family){families.add(family);}// 移除元素public void removeElement(IFamily family){families.remove(family);}// 访问元素,不同的访问者访问到的内容是不一样的public void accept(IVisitor visitor){for (IFamily family : families) {family.accept(visitor);}}
}
  • 8)测试类:
package com.pattern.demo01;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01 {public static void main(String[] args) {ObjectStructure structure=new ObjectStructure();structure.addElement(new ChildFamily("小刚",17));structure.addElement(new ParentFamily("爸",56));structure.addElement(new ChildFamily("妈",53));System.out.println("**************丈夫关心孩子们和父母**************");structure.accept(new FatherVisitor());System.out.println("**************妻子关心孩子们和父母**************");structure.accept(new MotherVisitor());}
}

20.3 访问者设计模式的优缺点

  • 优点:
    • 1)解耦了数据结构与数据操作,使得操作集合可以独立变化
    • 2)可以通过扩展访问者角色来实现对数据的不同操作,扩展性好
    • 3)各角色职责分离,符合单一职责原则
  • 缺点:
    • 1)无法增加元素类:若系统数据结构对象易于发生变化,如经常有新的元素增加进来,则访问者必须增加对应元素的操作,违背了开闭原则;
    • 2)访问者模式为了实现不同的访问者访问不同的元素达到不同的效果,所以访问者依赖的是具体元素类型,而不是抽象类,违背了依赖倒置原则;

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

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

相关文章

计算机网络基础 VLSM----可变长子网掩码;CIDR技术----无类域间路由;

VLSM----可变长子网掩码&#xff1a; 概述&#xff1a; 通过网络位向主机位借位的方式&#xff0c;延长子网掩码&#xff0c;从而达到将一个大网络划分为多个小网络&#xff1b;借出的位数称之为子网位&#xff0c;决定了能划分网络的个数。 优点&#xff1a; 更高效的利用…

记一次导入下载好的源码工程到本地工程异常解决方案

今天在学习okhttp相关视频时&#xff0c;安装视频的操作在自己的工程中引入三方的模块&#xff0c;但是发现引入后和预期的不一致。不一致指的是&#xff0c;视频中以module方式引入sample-okhttp并解决冲突后&#xff0c;sample-okhttp能够被android stuidio识别为applicayion…

Style样式设置器

构成Style最重要的两种元素&#xff1a; Setter类帮助我们设置控件的静态外观风格 Trigger类则帮助我们设置控件的行为风格。 Setter,设置器&#xff0c;我们给属性赋值的时候一般都采用“属 性名属性值”的形式 上面的例子中针对TextBlock的Style&#xff0c;Style中使用 若…

解决csdn强制关注博主才能阅读文章

问题 有的时候查阅资料的时候,关注博主并不是很方便,查csdn会出现下面的提示解决办法 打开控制台输入以下代码: var article_content=document.getElementById("article_content"); article_content.removeAttribute("style");var follow_text=document…

深入理解计算机系统——第七章 Linking

深入理解计算机系统——第七章 Linking7.1 Compiler Drivers7.2 Static Linking7.3 Object Files7.4 Relocatable Object Files7.5 Symbols and Symbol Tables7.6 Symbol Resolution7.6.1 How Linkers Resolve Duplicate Symbol Names7.6.2 Linking with Static Libraries7.6.3…

人体神经元结构示意图,神经细胞内部结构图

人体神经结构图&#xff1f;&#xff1f;&#xff1f;&#xff1f; 谷歌人工智能写作项目&#xff1a;神经网络伪原创 下图为神经系统的结构示意图&#xff0c;请根据图回答&#xff1a; &#xff08;1&#xff09;构成神经系统的结构、功能单位是神经元&#xff0c;图中E部分…

19【迭代器设计模式】

文章目录十九、迭代器设计模式19.1 迭代器设计模式简介19.1.1 迭代器设计模式概述19.1.2 迭代器设计模式的UML类图19.2 迭代器设计模式的实现19.3 迭代器设计模式的优缺点十九、迭代器设计模式 19.1 迭代器设计模式简介 19.1.1 迭代器设计模式概述 迭代器设计模式&#xff0…

DeFi借贷重新洗牌 透过协议变化能找到哪些新趋势?

在过去的几个月里&#xff0c;DeFi 借贷赛道产生了重大变化&#xff0c;1kx 研究员 Mikey 0x 对此场域重新进行梳理&#xff0c;BlockBeats 对其整理翻译如下&#xff1a; 本文内容将包括对新借贷协议的介绍、核心数据统计以及发展趋势&#xff0c;也许可以让我们大致把握下一…

Python3操作MongoDB数据库

Python3操作MongoDB数据库 文章目录Python3操作MongoDB数据库0. 写在前面1. 安装开源驱动库pymongo2. 参考0. 写在前面 Linux&#xff1a;Ubuntu Kylin 16.04MongoDB&#xff1a;MongoDB3.2.7Python&#xff1a;Anaconda With Python3.7 1. 安装开源驱动库pymongo pymongo驱动…

公众号题库搜题对接(免费接口)

公众号题库搜题对接(免费接口) 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&a…

用神经网络表示与逻辑,神经网络实现逻辑运算

数据挖掘中的神经网络和模糊逻辑的概念是啥&#xff1f; 【神经网络】人工神经网络&#xff08;Artificial Neural Networks&#xff0c;简写为ANNs&#xff09;也简称为神经网络&#xff08;NNs&#xff09;或称作连接模型&#xff08;Connection Model&#xff09;&#xff…

Frp内网穿透win系统实录

文章目录前言公网服务器端配置基于Docker配置简单文件配置内网服务器端配置frpc配置安装OpenSSH服务配置连接XShell和Xftp连接前言 由于实验室的某些原因&#xff0c;分配了一台win10的服务器&#xff08;QAQ&#xff09;&#xff0c;但是由于服务器在内网&#xff0c;无法访问…

【常用排序算法】

文章目录写在最前面只想用其中的某个算法&#xff1f;类关系图工具类NumberArrayUtil用于测试排序的父类 SortTest冒泡排序堆排序插入排序归并排序快速排序选择排序希尔排序写在最前面 只想用其中的某个算法&#xff1f; 如果你只是想要对应的排序算法&#xff0c;可删除每个…

A-Level数学P4:反证法题型变革趋势

历年来&#xff0c;真题中Prove by contradiction的常见题型有三类&#xff1a; 1►Even/Odd相关证明2►Multiple of 3相关证明3►Irrational number相关证明 但是从2022年开始&#xff0c;该考点有越变越活的趋势。不再局限于书本上出现过的习题类型&#xff0c;而是进一步考察…

SpringBoot生产监控

文章目录一、健康监控简介1、介绍2、SpringBoot准备工作3、其他二、健康检测触达关键组件1、内置组件健康详情2、自定义组件健康详情3、自定义多 HealthIndicator 聚合三、对外暴露应用内部重要组件的状态1、内部状态数据暴露2、JMX MBean四、指标 Metrics 快速定位五、总结一、…

String字符串拼接原理

前言 明白什么是引用&#xff0c;什么是该引用指向的真正对象。 对于基本数据类型比较的是值&#xff0c;对于引用数据类型比较的是指向的对象的地址&#xff0c;即两者指向的是否是同一个对象。 String s "gzc";上述代码中s为变量引用&#xff0c;它存在于栈中&am…

JAVA毕设项目商店管理系统(java+VUE+Mybatis+Maven+Mysql)

JAVA毕设项目商店管理系统&#xff08;javaVUEMybatisMavenMysql&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技…

wordpress字体个性化插件

wordpress字体插件可以对我们发布的文档字体大小、颜色、以及繁体简体进行切换。整洁的页面有助于提升用户阅读体验。wordpress字体插件具有可视化的字体修改页面&#xff0c;可以让我们调整出自己中意的文字&#xff0c;打造属于自己的个性化WordPress。 wordpress字体插件不需…

【Java】ArrayList和LinkedList区别?想秒懂就进来看!

ArrayList和LinkedList区别&#xff1f;1.底层结构不同2.ArrayList 和 LinkedList 都实现了 List 接口3.查询的对比4.添加的对比4.1 ArrayList 的添加操作4.1.1 在最后的位置添加元素4.1.2 在指定位置添加元素4.2 LinkedList 的添加操作5.总结5.1 以下情况使用 ArrayList5.2 以…

NXP i.MX 8M Mini开发板(4核 ARM Cortex-A53)硬件原理图规格说明书

前 言 本文档主要介绍NXP i.MX 8M Mini开发板硬件接口资源以及设计注意事项等内容。 创龙科技的NXP i.MX 8M Mini开发板是一款基于NXP i.MX 8M Mini的四核ARM Cortex-A53 + 单核ARM Cortex-M4异构多核处理器设计的高性能开发板,由核心板和评估底板组成。ARM Cortex-A53(64-b…