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


    介绍

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

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

    应用场景

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

    角色和职责

    • 访问者角色 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
  • 相关阅读:
    boost之内存池
    深挖 Python 元组 pt.1
    qt多线程编程,信号绑定成功,槽函数不响应问题排查处理及总结
    csdn怎么提问问题?
    Banana Pi BPI-W3(Armsom W3)RK3588开当板之调试UART
    python零基础看完必会安装和配置环境,文末附下载安装包
    如何获取量化交易历史复权数据?
    Leetcode81. Search in Rotated Sorted Array II
    如何简单挖掘公益SRC?
    装饰装修婚纱摄影类小程序开发
  • 原文地址:https://blog.csdn.net/maoyuanming0806/article/details/125518333