Java设计模式-访问者模式、访问者模式怎么使用,具体是怎么用

news2024/11/17 14:33:49

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用!

6.10 访问者模式

6.10.1 定义

封装一些作用域某种数据结构中的各元素的操作,可以在不改变此数据结构的前提下定义作用于这些元素的新操作

6.10.2 结构

  • 抽象访问者角色(Visitor):定义了对每个元素访问的行为,参数是可以访问的元素,理论上方法个数与元素类个数(Element的实现类个数)一样,所以访问者模式要求元素类个数不能改变
  • 具体访问者角色(Concrete Visitor):给出对每个元素类访问所产生的的具体行为
  • 抽象元素角色(Element):定义了一个接受访问者类的方法,意义是指每一个元素都要可以被访问者访问
  • 具体元素角色(Concrete Element):提供接受访问方法的具体实现,通常情况下使用访问者提供的访问该元素类方法
  • 对象结构角色(Object Structure):定义当中所提到的对象结构,对象结构是一个抽象表述,具体可理解为一个具有容器性质或符合对象特性的类,会含有一组元素,并且可以迭代这些元素,供访问者访问

6.10.3 案例(喂宠物)

  • 抽象访问者
public interface Person {  
    public void feed(Animal animal);  
}
  • 抽象元素
public interface Animal {  
    public void accept(Person person);  
}
  • 具体元素
public class Cat implements Animal{  
    @Override  
    public void accept(Person person) {  
        System.out.println("好吃,喵喵~~");  
    }  
}
public class Dog implements Animal{  
    @Override  
    public void accept(Person person) {  
        System.out.println("好吃,汪汪~~");  
    }  
}
  • 具体访问者
public class Owner implements Person{  
    @Override  
    public void feed(Animal animal) {  
        animal.accept(this);  
    }  
}
public class Someone implements Person{  
    @Override  
    public void feed(Animal animal) {  
        animal.accept(this);  
    }  
}
  • 对象结构
public class Home {  
    private List<Animal> list = new ArrayList<Animal>();  
//    添加宠物  
    public void addAnimal(Animal animal)  
    {  
        list.add(animal);  
    }  
//    喂养宠物  
    public void action(Person person){  
        for (Animal animal : list) {  
            person.feed(animal);  
        }  
    }  
}
  • 测试
    public static void main(String[] args) {  
        Home home = new Home();  
//        创建宠物对象  
//        添加宠物  
        home.addAnimal(new Dog());  
        home.addAnimal(new Cat());  
//        喂养着  
        Owner owner = new Owner();  
        Someone someone = new Someone();  
        home.action(owner);  
        home.action(someone);  
    }
  • 结果
    在这里插入图片描述

  • 类图![[Pasted image 20230116195922.png]]

6.10.4 优缺点

6.10.4.1 优点

  • 扩展性好:在不修改对象结构中元素的情况下,为对象结构中元素添加新功能
  • 复用性好:通过访问者来定义整个对象结构通用的功能,从而提高复用程度
  • 分类无关行为:通过此模式分离无关行为,将相关行为封装在一起,构成一个访问者,故每个访问者功能单一

6.10.4.2 缺点

  • 对象结构变化很困难:每增加一个新的元素类,都在每个具体访问者类中增加相应的具体操作,违背了“开闭原则”
  • 违反依赖倒置原则:此模式依赖具体类,而没有依赖抽象类

6.10.5 使用场景

  • 对象结构相对稳定,但其操作算法经常变化的程序
  • 对象结构中对象需要提供多种不同且不相关的操作,且要避免这些操作变化影响对象的结果

6.10.6 扩展

访问者模式使用了一种双分派技术

6.10.6.1 分派

  • 变量静态类型:变量被声明时的类型
  • 明显类型:也称静态类型
  • 变量实际类型:变量所引用的对象的真实类型
  • 比如:Map map = new HashMap(),map静态类型是Map,实际类型是HashMap
  • 分派:根据对象的类型而对方法的选择,分为两类:
    • 静态分派(Static Dispatch):发生在编译时期,根据静态类型信息选择,方法重载就属于静态分派
    • 动态分派(Dynamic Dispatch):发生在运行时期,动态地置换方法,Java通过重写支持动态分派

6.10.6.2 动态分派

代码如下:

public class Animal {  
    public void execute(){  
        System.out.println("Animal");  
    }  
}
public class Cat extends Animal{  
    public void execute(){  
        System.out.println("Cat");  
    }  
}
public class Dog extends Animal{  
    public void execute(){  
        System.out.println("Dog");  
    }  
}
public static void main(String[] args) {  
    Animal a = new Dog();  
    Animal a1 = new Cat();  
    a.execute();  
    a1.execute();  
}

结果是Dog和Cat输出,运行执行的是子类方法,多态
Java编译器在编译时期并不晓得哪些代码会被执行,因为编译器仅仅知道对象静态类型,不知对象真实类型,方法调用则是根据真实类型来执行,不是静态类型

6.10.6.3 静态分派

代码如下:

public class Animal {  
}
public class Cat extends Animal {  
}
public class Dog extends Animal {  
}
public class Execute {  
    public void execute(Animal a){  
        System.out.println("Animal");  
    }  
    public void execute(Dog dog){  
        System.out.println("Dog");  
    }  
    public void execute(Cat cat){  
        System.out.println("Cat");  
    }  
}
public static void main(String[] args) {  
    Animal a = new Animal();  
    Animal a1 = new Dog();  
    Animal a2 = new Cat();  
    Execute execute = new Execute();  
    execute.execute(a);  
    execute.execute(a1);  
    execute.execute(a2);  
}

结果全是Animal,静态分派,在编译时期完成

6.10.6.4 双分派

即在选择方法的时候,不仅根据消息接收者运行时区分,还要根据参数类型运行区分,代码如下:

public class Animal {  
    public void execute(Execute e){  
		e.execute(this);
    }  
}
public class Cat extends Animal {  
    public void execute(Execute e){  
        e.execute(this); 
    }  
}
public class Dog extends Animal {  
    public void execute(Execute e){  
        e.execute(this);
    }  
}
public class Execute {  
    public void execute(Animal a){  
        System.out.println("Animal");  
    }  
    public void execute(Dog dog){  
        System.out.println("Dog");  
    }  
    public void execute(Cat cat){  
        System.out.println("Cat");  
    }  
}
public static void main(String[] args) {  
    Animal a = new Animal();  
    Animal a1 = new Dog();  
    Animal a2 = new Cat();  
    Execute execute = new Execute();  
    a.execute(execute);  
    a1.execute(execute);  
    a2.execute(execute);  
}

结果为Animal、Dog、Cat。
上述测试代码将Execute对象作为参数传递给Animal类型的变量调用方法,这是第一次分派,是方法重写,动态分派,即执行的是实际类型中方法,同时将自己this作为参数传递进去,完成第二次分派,其中Execute类有多个重载方法,传递的是this,也是具体的实际类型
本质:
动态绑定,即在重载方法委派前加上继承体系中覆盖环节

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

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

相关文章

2023年新年烟花代码(背景音乐完整版)

文章目录前言烟花效果展示使用教程查看源码HTML代码CSS代码JavaScript新年祝福前言 大家过年好&#xff01;新春佳节&#xff0c;在这个充满喜悦的日子里&#xff0c;愿新年的钟声带给你一份希望和期待&#xff0c;我相信&#xff0c;时空的距离不能阻隔你我&#xff0c;我的祝…

Solidity 中的数学(第 5 部分:指数和对数

本文是关于在 Solidity 中进行数学运算的系列文章中的第五篇。这次的主题是&#xff1a;指数和对数 介绍 几个世纪以来&#xff0c;对数被用来简化计算。在电子计算器广泛普及之前&#xff0c;计算尺、基于对数的机械计算器是工程师职业的标志。 对数函数连同指数函数&#x…

【matplotlib】21.多图合并【python3、numpy、pandas、matplotlib完结】

#【matplotlib】21.多图合并 2023.1.20 python3、numpy、pandas、matplotlib完结 新年快乐&#xff01;&#xff01; 21.1 多合一显示 21.1.1 均匀分布 方法很简单 就是一张图 分几块 第一张占几块 从哪开始&#xff1b;第二张… plt.subplot() # 打开一个窗口 import ma…

Redis数据类型简介

目录 1、字符串(Strings) 1.1、底层实现 1.2、基本命令 1.3、应用场景 2、列表(Lists) 2.1、底层实现 2.2、基本命令 2.3、应用场景 3、集合(Sets) 3.1、底层实现 3.2、基本命令 3.3、应用场景 4、哈希(Hashes) 4.1、底层实现 4.2、基本命令 4.3、应用场景 5、…

Caché数据库简要记录

前一阵子&#xff0c;实施的小伙伴找过来问我用过 Cach 数据库吗&#xff1f;我当时有点懵&#xff1f;难道是 redis、memcached 之流&#xff1f;后来我特意去搜索了一下&#xff0c;还真是有一款数据库叫做 Cach Database。 这里做一下简单的记录吧&#xff0c;Cach 在医疗系…

Mine Goose Duck 0.1版本发布

我本次制作了一款MC版的Goose Goose Duck模组&#xff0c;游戏版本是Forge 1.19.2。 1.身份物品 熟悉鹅鸭杀的朋友都知道游戏中含有许多的身份&#xff0c;有好人、坏人、中立三个阵营&#xff0c;本次我加入了原作中的一些基本角色&#xff1a; 1.警长 你可以杀死怪物但错…

DFS(三)电话号码的字母组合

数组版本 哈希版本&#xff1a; 一、17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#x…

Elasticsearch7.8.0版本高级查询——范围查询文档

目录一、初始化文档数据二、范围查询文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; {"name":"张三","age"…

Git的安装与使用

目录 一、简介 1. Git 是什么&#xff1f; 2. 集中式和分布式 二、Git 环境搭建 1. Linux 下安装 2. Windows 下安装 三、创建版本库 四、把文件添加到版本库 1. 添加并提交 2. 仓库状态 3. 版本回退 &#xff08;1&#xff09;查看提交日志 &#xff08;2&#xff0…

量化交易-因子有效性分析

量化交易-因子有效性分析一、 因子的 IC 分析2. 信息系数3. 举例4. 因子处理4.1 去极值4.2 标准化4.3 市值中性化一、 因子的 IC 分析 判断因子与收益的相关性强度 分析结果 因子平均收益IC meanIC stdIC > 0.02&#xff1a;IC大约0.02的比例&#xff0c;越大越严格IR&…

leetcode刷题记录总结-1. 数组

文章目录一、二分查找[704. 二分查找](https://leetcode.cn/problems/binary-search/)题解小结[35. 搜索插入位置](https://leetcode.cn/problems/search-insert-position/)题解1&#xff1a;暴力解法题解2&#xff1a;二分法[34. 在排序数组中查找元素的第一个和最后一个位置]…

Day865.基础架构 -MySQL实战

基础架构&#xff1a;一条SQL查询语句是如何执行的 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的关于基础架构&#xff1a;一条SQL查询语句是如何执行的的内容。 经常说&#xff0c;看一个事儿千万不要直接陷入细节里&#xff0c;应该先鸟瞰其全貌&#xff0c;这样能够…

01-使用Camera Raw滤镜调色

1.需求展示 点击下载图片素材 原图 调色后, 具有电影感 2.操作步骤 1.打开原图 1.我使用的是ps2018, 打开原图, 图层名字可以自定义 2.拷贝底片建立一个新图层 养成好习惯, 每种操作都建立新图层来进行, 这样如果修坏了, 直接把该图层删除就行了, 还原图片比较快捷 3…

[QMT]03-让QMT支持从Tushare获取数据

QMT安装python第三方库为了兼容性&#xff0c;需要本地使用python3.6.8版本&#xff0c;因为刚刚下载的QMT python版本就是3.6.8.如果你本地有其他python版本的话&#xff0c;建议使用虚拟环境操作。这样不会影响你原有的python版本以及已经安装的第三方库。因为一机装多版本的…

Java设计模式-中介模式/中介模式具体怎么使用,使用场景又是什么

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.8 中介者模式 6.8.1 定义 调停模式&#xff0c;定义一个中介角色来封装一系列对象的之间交互&#xff0c;使元有对象之间的耦合松散&#xff0c;且可以独立改变…

2023年春节祝福第二弹——送你一只守护兔,让它温暖每一个你【html5 css3】画会动的小兔子,炫酷充电,字体特效

2023年春节祝福第二弹 送你一只守护兔&#xff0c;让它温暖每一个你&#xff01; 【html5 css3】画一只会动的兔子 目录 一、送你一只守护兔&#xff0c;效果图 二、前言 三、代码解释及部分特效教程 &#xff08;1&#xff09;、css3 立体字 &#xff08;2&#xff09;…

普中科技MicroPython基于esp32的基础教程-01

课程链接 3.5-Python基础--代码注释_哔哩哔哩_bilibili 学习目的 复习和加深对Python的学习和使用&#xff0c;将Python的使用融汇于硬件使用中。因此笔记记录的内容都是我之前遗忘的或者重要的知识点&#xff0c;选择性记录视频笔记&#xff0c;在开发的过程中对于遗忘的知识…

基于Power BI的终端产品销售ABC分析

一、原理 ABC分析&#xff0c;是由帕累托法则演化而来&#xff0c;一般认为A类产品带来70%的收入&#xff0c;B类产品带来20%的收入&#xff0c;C类产品带来10%的收入&#xff0c;所以ABC分析又称70/20/10分析。 二、数据源 某终端《8~10月商品月台帐》 问题&#xff1a; 1…

计算机网络——UDP与TCP

一、运输层的作用 运输层在整个网络体系结构中位于面向通信部分的最高层&#xff0c;同时也是用户功能中的最低层。它提供的是应用进程间的逻辑通信。所谓逻辑通信&#xff0c;指的是它屏蔽了下层网络的细节&#xff0c;使得进程看见的就是好像在两个运输层实体之间有一条端到…

二分、复杂度、动态数组、哈希表

1.二分法 不一定一定有序&#xff0c;比如找局部最小值就可以不有序 有序数组中找到num 用对数器生成随机数组来校验find()方法是否正确 public class Code01_BSExist {//有序数组中找到num//arr保证有序public static boolean find(int[] arr, int num) {if (arr null || …