[23种设计模式][行为型]11.访问者模式

50 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

1.意图:

表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

2.适用性:

·一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
·需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
·定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

3.访问者(Visitor)模式的构成:

1.抽象访问者(Visitor)角色:为对象结构类中的每一个ConcreteElement的类声明一个Visit操作。
2.具体访问者(ConcreteVisitor)角色:实现每个由Visitor声明的操作。
3.元素(Element)角色:定义一个Accept操作,它以一个访问者为参数。
4.具体元素(ConcreteElement)角色:实现Accept操作,该操作以一个访问者为参数。
5.对象结构类(ObjectStructure)角色:能枚举它的元素。可以提供一个高层的接口以允许访问者访问它的元素。

4.访问者模式UML类图:

Image.png

5.访问者模式UML时序图:

Image.png

6.代码示例:

Image.png

抽象元素:

public abstract class Element {

    public abstract void accept(Visitor visitor);
}

具体元素A:

public class ConcreteElementA extends Element {

    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementA(this);
    }
}

具体元素B:

public class ConcreteElementB extends Element {

    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementB(this);
    }
}

抽象访问者:

public abstract class Visitor {

    public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);

    public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}

具体访问者1:

public class ConcreteVisitor1 extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println("visited by concreteElementA: " + this.getClass().getName());
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println("visited by concreteElementB: " + this.getClass().getName());
    }
}

具体访问者2:

public class ConcreteVisitor2 extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println("visited by concreteElementA: " + this.getClass().getName());
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println("visited by concreteElementB: " + this.getClass().getName());
    }
}

对象结构类:

public class ObjectStructure {

    private ArrayList<Element> list = new ArrayList<>();

    public void attach(Element element) {
        list.add(element);
    }

    public void detach(Element element) {
        list.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element e : list) {
            e.accept(visitor);
        }
    }
}

客户端:

public class Client {

    public static void main(String[] args) {

        ObjectStructure o = new ObjectStructure();

        o.attach(new ConcreteElementA());
        o.attach(new ConcreteElementB());

        ConcreteVisitor1 v1 = new ConcreteVisitor1();
        ConcreteVisitor2 v2 = new ConcreteVisitor2();

        o.accept(v1);

        System.out.println("--------");

        o.accept(v2);
    }
}