设计模式之访问者模式

大兔子大兔子 提交于 2020-03-09 16:52:51

访问者模式

1.简单介绍

  • 访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,可以在不改变结构的前提下定义新的操作(作用于这些元素)
  • 访问者模式主要是将数据结构和数据的操作进行分离,解决了数据结构操作耦合性的问题
  • 访问者模式的基本工作原理是: 在被访问的类里提供一个对外接待访问者的方法
    void accept(Visitor visitor)

2.访问者中的角色

  1. Visitor 抽象访问者,为该对象结构中的ConcreteElement的每一个类声明一个访问操作
  2. ConcreteVisitor 具体的访问者,实现每个有Visitor声明的操作
  3. Element: 定义了一个accept操作,可以接受访问者对象
  4. ConcreteElement: 具体的待访问类,实现accept方法(内部聚合访问者)
  5. ObjectStructure访问元素的集合(多个Element),便于统一规划

3.访问者模式的结构图在这里插入图片描述

4.实现简单的访问者模式代码

import com.liz.GOF23.visitor.relearn.visitor.Visitor;
//!!!被访问类的接口
//抽象元素(内部有accept方法用于接收访问者)
public interface Element {
    void accept(Visitor visitor);
}

//!!!具体被访问类A
public class ConcreteElemA implements Element {
    @Override
    public void accept(Visitor visitor) {
       visitor.visit(this);
    }
    //加入额外操作
    public String operationA(){
        return "具体元素A的操作";
    }
}

//!!!具体被访问类B
public class ConcreteElemB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    //加入额外操作
    public String operationB(){
        return "具体元素B的操作";
    }
}

//!!!抽象访问者
public interface Visitor {
    //需要体现出个性 而不是统一化操作
    default void visit(ConcreteElemA elementA){}
    default void visit(ConcreteElemB elementB){}
}
//!!!具体访问者A
public class ConcreteVisitorA implements Visitor {
    @Override
    public void visit(ConcreteElemA element) {
        System.out.println("具体访问者A访问:"+element.operationA());
    }
}

//!!!具体访问者B
public class ConcreteVisitorB implements Visitor {
    @Override
    public void visit(ConcreteElemB elementB) {
        System.out.println("具体访问者B访问:"+elementB.operationB());
    }
}

//访问元素的集合
public class ObjectStructure {
    private List<Element> list=new ArrayList<Element>();
    public void accept(Visitor visitor){
        for (Element element : list) {
            //数据和visitor之间进行适应
            element.accept(visitor);
        }
    }
    public void add(Element element){
        list.add(element);
    }
    public void remove(Element element){
        list.remove(element);
    }
}

//Client
public class Client {
    public static void main(String[] args) {
        ObjectStructure os = new ObjectStructure();
        os.add(new ConcreteElemA());
        os.add(new ConcreteElemB());
        Visitor visitorA = new ConcreteVisitorA();
        os.accept(visitorA);
        System.out.println("===============");
        Visitor visitorB = new ConcreteVisitorB();
        os.accept(visitorB);
    }
}

运行结果:
在这里插入图片描述

5.访问者模式细节:

  • 访问者模式的应用场景: 需要对一个具体结构的对象进行很多不同的操作(这些操作彼此之间没有关联),同时需要避免让这些操作影响对象的类。可以采用访问者模式解决

  • 优点
    * 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
    * 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
    * 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
    *符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

  • 缺点

    • 增加新的元素类十分困难,需要在具体访问者类中增加相应的操作,违反了开闭原则。
    • 破坏了封装性,访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
    • 违反了依赖倒置原则,访问者模式依赖了具体类,而没有依赖抽象类。

参考资料:http://c.biancheng.net/view/1397.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!