• 访问者模式


    测评系统

    完成一个测评系统需求

    1. 将观众分为男人和女人两类,对歌手进行测评,当看完某个歌手的表演后,得到他们对不同歌手的评价,假设初始评价两种:成功、失败

    传统方案

    在这里插入图片描述
    将不同的观众分为不同的类,然后每个类里面实现评价的功能

    1. 在系统扩展,增加新的功能时,对代码的改动较大,违反了ocp原则,不利于维护(比如增加一种评价)
    2. 扩展性性不好,对于新增人员类型,管理方法都不好做

    访问者模式

    基本介绍

    1. 访问者模式封装了一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作
    2. 主要将数据结构和数据操作分离,解决数据结构和操作耦合性问题
    3. 访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口
    4. 访问者模式的主要应用场景是:需要对一个对象结构中的对象进行很多不同的操作,同时避免这些操作污染这些对象的类,将类结构和操作分离

    原理

    在这里插入图片描述

    1. Visitor:抽象的访问者,为该对象结构中的ConcreteElement的每一个类声明一个visit操作
    2. ConcreteVisit:是一个具体的访问值,实现每一个由Visitor声明的操作,是每个操作的具体实现
    3. ObjectStructure:枚举它的元素提供一个高层的接口,用来允许访问者访问元素
    4. Element:定义了一个accept方法,可以接收访问者对象操作
    5. ConcreteElement:实现了accept方法细节

    访问者模式解决评测需求

    在这里插入图片描述

    /***
     * @author shaofan
     * @Description 访问者模式解决评测需求
     */
    public class Visitor {
        public static void main(String[] args) {
            ObjectStructure objectStructure = new ObjectStructure();
            objectStructure.attach(new Man());
            objectStructure.attach(new Woman());
            objectStructure.display(new Success());
        }
    }
    
    abstract class Action{
        abstract void getManResult(Man man);
        abstract void getWomanResult(Woman woman);
    }
    
    class Success extends Action{
    
        @Override
        void getManResult(Man man) {
            System.out.println("男人"+man.getName()+"觉得成功");
        }
    
        @Override
        void getWomanResult(Woman woman) {
            System.out.println("女人"+woman.getName()+"觉得成功");
        }
    }
    
    class Fail extends Action{
    
        @Override
        void getManResult(Man man) {
            System.out.println("男人"+man.getName()+"觉得失败");
        }
    
        @Override
        void getWomanResult(Woman woman) {
            System.out.println("女人"+woman.getName()+"觉得失败");
        }
    }
    
    abstract class Person{
        String name = "匿名";
        public void setName(String name){
            this.name = name;
        }
        public String getName(){
            return this.name;
        }
        abstract void accept(Action action);
    }
    
    class Man extends Person{
    
        @Override
        void accept(Action action) {
            action.getManResult(this);
        }
    }
    
    /***
     * 这里使用到双分派,首先将操作作为参数传递到类中,然后调用操作方法时,再将自身对象传递到操作中
     */
    class Woman extends Person{
    
        @Override
        void accept(Action action) {
            action.getWomanResult(this);
        }
    }
    
    class ObjectStructure{
        private List<Person> persons = new LinkedList<>();
        public void attach(Person person){
            persons.add(person);
        }
        public void detach(Person person){
            persons.remove(person);
        }
    
        public void display(Action action){
            for (Person person : persons) {
                person.accept(action);
            }
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    双分派

    1. 双分派可以不管类怎么变化,都能找到期望的方法运行,双分派一份围着得到执行的操作取决于请求的种类和接收者的类型
    2. 例如上述中,Action新增与Person是无关的,Person只用将自身传入Action中,新增一个Action只需要增加一个Action子类即可
    3. 在访问者模式中,数据结构应该是固定的,改动的一方是Action

    总结

    优点

    1. 访问者模式符合单一职责原则,让程序具有优秀的扩展性,灵活性非常高
    2. 访问者模式可以对功能尽心过统一,可以作报表、UI、拦截器、过滤器,适用于数据结构相对稳定的系统

    缺点

    1. 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是i迪米特法则不建议的,造成了具体元素变更比较困难
    2. 违背了依赖倒转原则,访问者依赖的是具体类,而不是抽象
    3. 如果一个系统由比较稳定的数据结构,又有进场变化的功能需求,那么访问者模式是比较合适的
  • 相关阅读:
    sendfile数据copy流程
    C++提高编程
    浙大数据结构慕课课后题(03-树2 List Leaves)
    看了这篇MySQL,开发功力又升级
    明美新能源冲刺深交所:年应收账款超6亿 拟募资4.5亿
    12.NLP中的RNN、LSTM、GRU
    SpringBoot 搭建基于 MinIO 的高性能存储服务
    通过ElementUi在Vue搭建的项目中实现CRUD
    [附源码]Python计算机毕业设计Django电影推荐网站
    最新大厂数据湖面试题,知识点总结
  • 原文地址:https://blog.csdn.net/m0_48468380/article/details/126389237