• 【设计模式】Java设计模式 - 访问者模式


    【设计模式】Java设计模式 - 访问者模式

    😄 不断学习才是王道
    🔥 继续踏上学习之路,学之分享笔记
    👊 总有一天我也能像各位大佬一样
    🏆 一个有梦有戏的人 @怒放吧德德
    🌝分享学习心得,欢迎指正,大家一起学习成长!

    请添加图片描述

    简介

    在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
                                                                                                                                                        ———— 菜鸟联盟

    访问者模式解析

    访问者模式主要是将数据操作和数据结构分离开来,解决他们的耦合性问题。就是在访问类里面添加对外提供接待访问者的接口。
    浅浅的理解,实际上就是有个元素接口类,里面包含未实现的方法,并且需要将访问者接口类对象带进去;在具体扩展的实体类中实现了元素接口类的方法,也就是调用了访问者对象的方法,这就相当于真正实现的方法都是由访问者接口类的子类去实现,这就形成了元素实体的可扩展,访问者的可扩展,并且他们都互不影响。
    原理UML如图:
    在这里插入图片描述

    角色与职责

    • Visitor 访问者,为对象ConcreteElement类声明了visit方法。
    • ConcreteVisitor 具体访问者,实现Visitor的每一个方法。
    • ObjectStruture 能够枚举其他元素,用来允许访问者访问元素。
    • Element 接收访问者对象。
    • ConcreteElement 具体元素

    访问者模式实例

    采用汽车的例子来理解访问者模式,定义元素接口,将访问者接口对象带入,在具体的元素类中,通过访问者去调用相应方法。则访问者接口定义了元素所需的方法,由具体的访问者类去实现,数据结构是用来对元素进行管理,管理访问者能否访问元素。
    类图:
    在这里插入图片描述
    代码如下:

    ①、定义访问者接口

    定义元素各自所需的方法,这里定义vidit方法,通过参数来区分。

    package com.lyd.demo.visitor;
    
    import com.lyd.demo.element.car.Benz;
    import com.lyd.demo.element.car.HongQi;
    
    /**
     * @Author: lyd
     * @Description: 访问者接口
     * @Date: 2022-09-04
     */
    public interface ICarPartVisitor {
        public void visit(Benz benz);
        public void visit(HongQi hongQi);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ②、定义具体访问者

    编写所有具体元素的业务

    package com.lyd.demo.visitor;
    import com.lyd.demo.element.car.Benz;
    import com.lyd.demo.element.car.HongQi;
    /**
     * @Author: lyd
     * @Description: 具体访问者方法
     * @Date: 2022-09-04
     */
    public class CarDisplayVisitor implements ICarPartVisitor {
        @Override
        public void visit(Benz benz) {
            System.out.println(" 奔驰旗舰店汽车 ");
        }
        @Override
        public void visit(HongQi hongQi) {
            System.out.println(" 红旗旗舰店汽车 ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    ③、定义元素实体接口

    带入访问者接口类对象,由具体的元素去实现,通过访问者调用方法。

    package com.lyd.demo.element;
    import com.lyd.demo.visitor.ICarPartVisitor;
    /**
     * @Author: lyd
     * @Description: 元素实体接口类
     * @Date: 2022-09-04
     */
    public interface ICar {
        public void accept(ICarPartVisitor carPartVisitor);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ④、定义具体元素类

    这里使用了双分派,将具体状态传递到Benz中,完成第一次分派。
    通过访问者调用具体的方法,并且将自身对象作为参数,完成第二次分派。
    (红旗类也是如此)

    package com.lyd.demo.element.car;
    import com.lyd.demo.element.ICar;
    import com.lyd.demo.visitor.ICarPartVisitor;
    /**
     * @Author: lyd
     * @Description: 扩展的实体类 - 奔驰
     * @Date: 2022-09-04
     */
    public class Benz implements ICar {
        @Override
        public void accept(ICarPartVisitor carPartVisitor) {
            carPartVisitor.visit(this); // 将本身带过去
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ⑤、定义数据结构

    添加具体元素进来,通过循环遍历去调用各自的方法。

    package com.lyd.demo.structure;
    import com.lyd.demo.element.ICar;
    import com.lyd.demo.visitor.ICarPartVisitor;
    import java.util.LinkedList;
    import java.util.List;
    /**
     * @Author: lyd
     * @Description: 数据结构
     * @Date: 2022-09-04
     */
    public class ObjectStructure {
        // 聚合
        private List<ICar> cars = new LinkedList<ICar>();
        // 添加到链表
        public void attach(ICar car) {
            this.cars.add(car);
        }
        // 缩减链表
        public void remove(ICar car) {
            this.cars.remove(car);
        }
        // 显示
        public void display(ICarPartVisitor carPartVisitor) {
            for (ICar car : cars) {
                car.accept(carPartVisitor);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    ⑥、测试

    通过数据结构将对象添加进去,在通过具体的访问者去统一调用方法

    package com.lyd.demo.test;
    import com.lyd.demo.element.car.Benz;
    import com.lyd.demo.element.car.HongQi;
    import com.lyd.demo.structure.ObjectStructure;
    import com.lyd.demo.visitor.CarDisplayVisitor;
    /**
     * @Author: lyd
     * @Description: 测试
     * @Date: 2022-09-04
     */
    public class VisitorTest {
        public static void main(String[] args) {
            // 创建对象
            ObjectStructure objectStructure = new ObjectStructure();
            objectStructure.attach(new Benz());
            objectStructure.attach(new HongQi());
            CarDisplayVisitor carDisplayVisitor = new CarDisplayVisitor();
            objectStructure.display(carDisplayVisitor);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果
    在这里插入图片描述
    👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得一键三连哦!👍

    今天的内容理解不是那么简单,但实质上除了设计模式的思路,其实就是Java的面向对象知识,只要肯动手多敲,就容易理解。

    💓德德小建议:

    理解设计模式不是一件简单的事情,需要不断的学习和动手去练习,才能理解。只有掌握好设计模式,才能够真正的理解SpringAOP和Mybatis的底层原理。各位读者可以和我一样,动手敲一敲代码,甚至用不同的例子来做,通过debug一步一步调试,还有就是多看看别人的例子。能够有助于理解!谢谢各位观看指点!❤️ ❤️ ❤️

  • 相关阅读:
    若依框架的使用
    时间显示相关
    C primer plus学习笔记 —— 6、数组和指针
    智能优化与机器学习结合算法实现数据分类matlab代码清单
    TCPIP网络编程 学习笔记_1 --网络编程入门
    面试算法 二叉树的遍历,方法递归,前序遍历: 中序遍历: 后序遍历: 层序遍历
    微信小程序开发的OA会议之首页搭建
    c语言qsort函数使用教程
    linux安装kafka教程
    Java高级 设计模式
  • 原文地址:https://blog.csdn.net/qq_43843951/article/details/126696030