前言
本篇来讲讲行为型模式的最后一篇,访问者模式。
正文
概念
访问者模式,我们使用一个访问者类来访问数据对象,通常是为了不污染数据对象类,而实现的关键是在数据对象类中提供一个接待访问者的接口。
那这种设计模式了除了不污染原类,很大一部分原因是为了将数据结构与操作相分离。
实现
由于这种设计模式在开发中很少用,一般是在框架或者源码中才会使用到。所以这里我就简单实现一下概念。
首先访问者模式中有几个角色:
- Visitor(抽象访问者):抽象类或接口,对每一种具体元素类ConcreteElement声明一个操作方法,由具体访问者去实现。
- ConcreteVisitor(具体访问者):实现抽象访问者的方法。
- Element(抽象元素):一般会定义一个Accept方法,接受一个visitor对象作为参数。
- ConcreteElement(具体元素):具体实现抽象元素。
- ObjectStructure(对象结构):可以是任意一种数据结构,能枚举它包含的元素,并提供一个接口,允许visitor进行访问。
下面我将简单写写代码实现。
首先我们先定义抽象访问者吧。
1 2 3 4
| public interface Visitor { public void visit(ConcreteElementA element); public void visit(ConcreteElementB element); }
|
然后是具体访问者
1 2 3 4 5 6 7 8 9 10 11
| public class ConcreteVisitorA implements Visitor{ @Override public void visit(ConcreteElementA element) { System.out.println("访问 ElementA"); }
@Override public void visit(ConcreteElementB element) { System.out.println("访问 ElementB"); } }
|
接着定义抽象元素,有一个accept方法接收一个visitor对象。
1 2 3
| public interface Element { public void accept(Visitor visitor); }
|
然后是具体元素
1 2 3 4 5 6 7 8 9 10 11 12
| public class ConcreteElementA implements Element{ @Override public void accept(Visitor visitor) { visitor.visit(this); } } public class ConcreteElementB implements Element{ @Override public void accept(Visitor visitor) { visitor.visit(this); } }
|
我们定义一个对象结构来存放所有的元素,并且定义accept方法来逐个访问元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class ObjectStructure { private ArrayList<Element> elements = new ArrayList<>(); public void accept(Visitor visitor){ for (Element element: elements){ element.accept(visitor); } } public void addElement(Element element){ elements.add(element); } public void removeElement(Element element){ elements.remove(element); } }
|
我们编写客户端调用试试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Client { public static void main(String[] args) { Element elementA = new ConcreteElementA(); Element elementB = new ConcreteElementB(); Visitor visitor = new ConcreteVisitorA();
elementA.accept(visitor); elementB.accept(visitor);
ObjectStructure objectStructure = new ObjectStructure(); objectStructure.addElement(elementA); objectStructure.addElement(elementB); objectStructure.accept(visitor);
} }
|
那所以是否定义ObjectStructure取决于你是否需要同时访问多个元素。
书写代码之后,我第一感觉就是耦合较高,访问者与元素之间相互依赖极高。
优缺点
访问者模式的优点在于添加新的访问操作较为方便,无需修改元素类,修改抽象访问者及其具体访问者即可,并且类的职责更加清晰,元素类负责数据,而访问者负责访问,符合单一职责原则。
而缺点就是添加元素类就十分麻烦,添加一个元素类后,需要修改每个访问者的代码,违背了开闭原则。并且在依赖上,具体访问者依赖于具体元素类,没有依赖抽象对象。最后,为了供访问者访问,有时候元素类不得不暴露己类的某些细节,封装性被破坏。