• 设计模式与应用:访问者模式


    介绍

    一个实体,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间推移而变化(行为可扩展)

    原则就是:软件的开闭原则:对修改关闭,对扩展开放
    行为模式之一

    应用场景

    • 数据和使用者解耦,数据只对使用者暴露最少的功能接口来满足使用者的需求,并且不同使用者自己定义具体使用方案
    • 公园的访问设计

    角色和职责

    • 访问者角色 Visitor:为对象结构中具体元素角色声明一个访问操作接口
    • 具体访问者角色 Concrete Visitor:实现每个由访问者接口声明的操作
    • 元素角色 Element:定义一个Accept操作,它以一个访问者为参数
    • 具体元素角色 Concrete Element:实现Element定义的Accept操作
    • 对象结构角色 Object Structure:具备特征:
      • 能枚举他的元素
      • 可以提供一个高层的接口以允许该访问者访问他的元素
      • 可以是一个复合体或者一个集合

    结构图和代码UML

    在这里插入图片描述

    在这里插入图片描述

    代码实现

    这里以公园(元素)和清洁工(访问者)的关系来描述这个模式

    • 元素定义
    /**
     * element 元素的抽象
     */
    public interface ParkElement {
    
        public void accept(Visitor visitor);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    /**
     * 角色:具体访问元素
     * 公园元素 公园包括A部分和B部分
     */
    public class ParkConcreteElement implements ParkElement{
    
        private ParkAConcreteElement parkA;
        private ParkBConcreteElement parkB;
    
        public ParkConcreteElement() {
            this.parkA = new ParkAConcreteElement();
            this.parkB = new ParkBConcreteElement();
        }
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
            parkA.accept(visitor);
            parkB.accept(visitor);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    /**
     * 角色:具体访问元素
     * 公园A部分
     */
    public class ParkAConcreteElement implements ParkElement{
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    /**
     * 角色:具体访问元素
     * 公园B部分
     */
    public class ParkBConcreteElement implements ParkElement{
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 访问者定义
    /**
     * 角色:访问者 Visitor
     * 附加说明:这里定义了不同访问者有不同的visit方法
     * 扩展上:这里也可以实现成策略模式,一个visit方法接受ParkElement,根据不同子类实现不同的visit具体实现
     */
    public interface Visitor {
    
        public void visit(ParkConcreteElement park);
        public void visit(ParkAConcreteElement parkA);
        public void visit(ParkBConcreteElement parkB);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    /**
     * 角色:具体访问者 公园管理者
     **/
    public class VisitorManager implements Visitor{
        @Override
        public void visit(ParkConcreteElement park) {
            System.out.println("公园管理者视察Park");
        }
    
        @Override
        public void visit(ParkAConcreteElement parkA) {
            System.out.println("公园管理者视察ParkA");
        }
    
        @Override
        public void visit(ParkBConcreteElement parkB) {
            System.out.println("公园管理者视察ParkB");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    /**
     * 角色:具体访问者 清洁工A
     **/
    public class VisitorA implements Visitor{
        @Override
        public void visit(ParkConcreteElement park) {
    
        }
    
        @Override
        public void visit(ParkAConcreteElement parkA) {
            System.out.println("清洁工A清扫ParkA部分");
        }
    
        @Override
        public void visit(ParkBConcreteElement parkB) {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    /**
     * 角色:具体访问者 清洁工B
     **/
    public class VisitorB implements Visitor{
        @Override
        public void visit(ParkConcreteElement park) {
    
        }
    
        @Override
        public void visit(ParkAConcreteElement parkA) {
    
        }
    
        @Override
        public void visit(ParkBConcreteElement parkB) {
            System.out.println("清洁工B清扫ParkB部分");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 元素结构
    /**
     * 角色:访问元素构建
     * - 能枚举他的元素
     * - 可以提供一个高层的接口以允许该访问者访问他的元素
     * - 可以是一个复合体或者一个集合
     * 这里就简单创建一个单一的元素
     */
    public class ObjectStructure {
    
        private ParkElement park = new ParkConcreteElement();
    
        public ParkElement getPark() {
            return park;
        }
    
        public void setPark(ParkElement park) {
            this.park = park;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 测试
    /**
     * Client 测试
     */
    public class ClientTest {
    
        public static void main(String[] args) {
            // 通过对象结构获取访问元素(公园)
            ObjectStructure objectStructure = new ObjectStructure();
            ParkElement park = objectStructure.getPark();
    
            // 访问者A来了(清洁工A来了)
            VisitorA visitorA = new VisitorA();
            park.accept(visitorA);
    
            // 访问者B来了(清洁工B来了)
            VisitorB visitorB = new VisitorB();
            park.accept(visitorB);
    
            // 访问者C来了(管理员来了)
            VisitorManager visitorManager = new VisitorManager();
            park.accept(visitorManager);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    系统部署常用操作_查看硬盘大小_查看内存情况_查看某个端口是否被占用_telnet_远程scp复制拉取---Linux运维工作笔记055
    基于非支配排序遗传算法的多目标水光互补优化调度附Matlab代码
    net-java-php-python-学生入学信息管理系统计算机毕业设计程序
    hbase和aerospike基础概念
    解锁前端Vue3宝藏级资料 第四章 VUE常用 UI 库 1 ( element-plus,Ant ,naiveui,ArcoDesign)
    PMP每日一练 | 考试不迷路-9.12(包含敏捷+多选)
    Java基础进阶多线程-线程安全和synchronized关键字
    tiup mirror sign
    windows10系统下指定用户配置FTP服务器及多用户登录
    CCF CSP认证历年题目自练Day46
  • 原文地址:https://blog.csdn.net/maoyuanming0806/article/details/125518333