设计模式之访问者模式
定义
访问者(Visitor)模式:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
结构
- 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
- 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
- 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
- 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
- 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
类图
代码示例
- 抽象访问者(Visitor)
public interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
- 具体访问者(ConcreteVisitor)
public class ConcreteVisitorA implements Visitor{
@Override
public void visit(ConcreteElementA element) {
System.out.println("visitorA visit: " + element.operation());
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("visitorA visit: " + element.operation());
}
}
public class ConcreteVisitorB implements Visitor{
@Override
public void visit(ConcreteElementA element) {
System.out.println("visitorB visit: " + element.operation());
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("visitorB visit: " + element.operation());
}
}
- 抽象元素(Element)
public interface Element {
void accept(Visitor visitor);
}
- 具体元素(ConcreteElement
public class ConcreteElementA implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operation() {
return "ConcreteElementA's operation";
}
}
public class ConcreteElementB implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operation() {
return "ConcreteElementB's operation";
}
}
- 对象结构(Object Structure)
public class ObjectStructure {
private List<Element> list = new ArrayList<>();
public void accept(Visitor visitor) {
Iterator<Element> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next().accept(visitor);
}
}
public void add(Element element) {
list.add(element);
}
public void remove(Element element) {
list.remove(element);
}
}
测试类
public class Test {
public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
os.add(new ConcreteElementA());
os.add(new ConcreteElementB());
os.accept(new ConcreteVisitorA());
System.out.println("----------------------------");
os.accept(new ConcreteVisitorB());
}
}
输出结果:
visitorA visit: ConcreteElementA's operation
visitorA visit: ConcreteElementB's operation
----------------------------
visitorB visit: ConcreteElementA's operation
visitorB visit: ConcreteElementB's operation
总结
通常在以下情况可以考虑使用访问者(Visitor)模式:
- 对象结构相对稳定,但其操作算法经常变化的程序。
- 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
- 对象结构包含很多类型的对象,希望对这些对象实施一些依赖于其具体类型的操作。