0
点赞
收藏
分享

微信扫一扫

设计模式:访问者模式

高子歌 2022-04-13 阅读 157
java

Table Of Content

访问者模式的概念和具体实现

访问者模式中对象结构存储了不同类型的元素对象,以供不同访问者访问。访问者模式包括两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,一个是元素层次结构,提供了抽象元素和具体元素。相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同访问者以不同访问方式访问。在访问者模式中,增加新的访问者无须修改原有系统,系统具有较好的可扩展性。

访问者模式在不破坏类的前提下,为类提供增加新的新操作,其实现的关键是双分派(Double-Dispatch)的技术。 在访问者模式中 accept()操作是一个双分派的操作。具体调用哪一个具体的accept()操作,体现在handleRequest方法,有两个决定因素:

1)Element的类型。因为 accept()是多态的操作,需要具体的 Element 类型的子类才可以决定到底调用哪一个accept()实现,取决于对象结构类中添加的元素集合;

2)Visitor的类型。accept()操作有一个参数(Visitor visitor),要决定了实际传进来的 Visitor 的实际类别才可以决定具体是调用哪个 VisitConcrete()实现,取决于客户端进行访问的访问者身份。

//访问者接口
interface Visitor {

    /**
     * 访问ConcreteElementA,相当于为ConcreteElementA添加的新功能
     */
    public void visitConcreteElementA(ConcreteElementA elementA);

    /**
     * 访问ConcreteElementB,相当于为ConcreteElementB添加的新功能
     */
    public void visitConcreteElementB(ConcreteElementB elementB);

}

//元素对象抽象类
abstract class Element {

    //接受访问者的访问
    public abstract void accept(Visitor visitor);
}

//模拟A访问者
class ConcreteVisitorA implements Visitor {
    @Override
    public void visitConcreteElementA(ConcreteElementA elementA) {
        /**
         * 把访问ConcreteElementA时,需要执行的功能在这里进行实现 可能需要访问元素已有的功能,比如:operationA()
         */
        System.out.println("ConcreteVisitorA 访问 ==> ConcreteElementA 对象");

    }
    @Override
    public void visitConcreteElementB(ConcreteElementB elementB) {
        /**
         * 把访问ConcreteElementB时,需要执行的功能在这里进行实现 可能需要访问元素已有的功能,比如:operationB()
         */
        System.out.println("ConcreteVisitorA 访问 ==> ConcreteElementB 对象");
    }

}

//模拟B访问者
class ConcreteVisitorB implements Visitor {


    @Override
    public void visitConcreteElementA(ConcreteElementA elementA) {
        /**
         * 把访问ConcreteElementA时,需要执行的功能在这里进行实现
         * 可能需要访问元素已有的功能,比如:operationA()
         */
        System.out.println("ConcreteVisitorB 访问 ==> ConcreteElementA 对象");
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB elementB) {
        /**
         * 把访问ConcreteElementB时,需要执行的功能在这里进行实现 可能需要访问元素已有的功能,比如:operationB()
         */
        System.out.println("ConcreteVisitorB 访问 ==> ConcreteElementB 对象");

    }

}

//元素访问对象A
class ConcreteElementA extends Element {

    @Override
    public void accept(Visitor visitor) {
        // 回调访问者对象的相应方法
        visitor.visitConcreteElementA(this);
    }

    /**
     * 示例方法,表示元素已有的功能实现
     */
    public void operationA() {
        System.out.println("执行ConcreteElementA已有的operationA方法.");

    }
}

//元素访问对象B
class ConcreteElementB extends Element {

    @Override
    public void accept(Visitor visitor) {
        // 回调访问者对象的相应方法
        visitor.visitConcreteElementB(this);

    }

    /**
     * 示例方法,表示元素已有的功能实现
     */
    public void operationB() {
        System.out.println("执行ConcreteElementB已有的operationB方法.");

    }
}

//元素对象集合类,包括元素添加和元素访问
class ObjectStructure {
    /**
     * 示意,表示对象结构,可以是一个组合结构或者集合
     */
    private Collection<Element> col = new ArrayList<>();

    /**
     * 示意方法,提供给客户端操作的高层接口,让访问者对对象结构中的所有元素进行访问
     */
    void handleRequest(Visitor visitor) {
        //循环对象结构中的元素,进行访问
        for (Element element : col) {
            element.accept(visitor);
        }
    }

    /**
     * 示意方法,组建对象结构,向对象结构中添加元素
     */
    void addElement(Element element) {
        this.col.add(element);
    }
}

//客户端
class Client {
    public static void main(String[] args) {

        //创建对象结构
        ObjectStructure os = new ObjectStructure();

        //为对象结构中添加元素对象
        os.addElement(new ConcreteElementA());
        os.addElement(new ConcreteElementB());

        //创建访问者
        Visitor visitor = new ConcreteVisitorA();

        //调用对象结构的业务处理方法
        os.handleRequest(visitor);
    }
}

访问者模式的场景举例

一个商场(SuperMarket),通常都会包括(当然还会包含一些其他的组成部分):商店(Store)、监控室(MonitoringRoom)、卫生间(WaterCloset)。商场的访问者大致可以分为两大类:顾客(Customer)、商场工作人员(MarketStaff)。顾客可以逛商店、上卫生间,但却不能进入监控室;工作人员可以进入监控室、上卫生间,但却不能像顾客一样逛商店(除非他不想干了),也就是说对于商场的同一个地点,不同的访问者有不同的行为权限,而且访问者的种类很有可能需要根据时间的推移发生变化(没准哪天,工商局的人要来视察呢!此时就需要增加工商局人员的访问者了。)
在这里插入图片描述

参考博文:https://blog.csdn.net/pengjunlee/article/details/54429325

举报

相关推荐

0 条评论