前言 本篇来讲讲行为型模式的最后一篇,访问者模式。
正文 概念 访问者模式,我们使用一个访问者类来访问数据对象,通常是为了不污染数据对象类,而实现的关键是在数据对象类中提供一个接待访问者的接口。 那这种设计模式了除了不污染原类,很大一部分原因是为了将数据结构与操作相分离。
实现 由于这种设计模式在开发中很少用,一般是在框架或者源码中才会使用到。所以这里我就简单实现一下概念。 首先访问者模式中有几个角色:
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取决于你是否需要同时访问多个元素。 书写代码之后,我第一感觉就是耦合较高,访问者与元素之间相互依赖极高。
优缺点 访问者模式的优点在于添加新的访问操作较为方便,无需修改元素类,修改抽象访问者及其具体访问者即可,并且类的职责更加清晰,元素类负责数据,而访问者负责访问,符合单一职责原则。 而缺点就是添加元素类就十分麻烦,添加一个元素类后,需要修改每个访问者的代码,违背了开闭原则。并且在依赖上,具体访问者依赖于具体元素类,没有依赖抽象对象。最后,为了供访问者访问,有时候元素类不得不暴露己类的某些细节,封装性被破坏。