设计模式-访问者模式(visitor)
访问者模式
定义
表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变元素的类的前提下定义作用于这些元素的新操作。
结构
Visitor:抽象访问者类,为该对象结构中的每一个类声明visit操作。
ConcreteVisitor:具体抽象类,实现visit操作,将ConcreteElement作为方法参数。
Element:抽象元素类,定义一个accpet接口,将visior作为方法参数。
ConcreteElement:具体元素类,实现accept操作。
类图
抽象访问者:
abstract class Visitor {
private String action;
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
具体访问者A:
public class ConcreteVisitorA extends Visitor{
public ConcreteVisitorA(String action) {
this.setAction(action);
}
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(this.getAction()+"访问"+concreteElementA.getName());
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(this.getAction()+"访问"+concreteElementB.getName());
}
}
具体访问者B:
public class ConcreteVisitorB extends Visitor{
public ConcreteVisitorB(String action) {
this.setAction(action);
}
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(this.getAction()+"访问"+concreteElementA.getName());
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(this.getAction()+"访问"+concreteElementB.getName());
}
}
抽象元素:
abstract class Element {
private String name;
public abstract void accept(Visitor visitor);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
具体元素A:
public class ConcreteElementA extends Element{
public ConcreteElementA(String name) {
this.setName(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
具体元素B:
public class ConcreteElementB extends Element{
public ConcreteElementB(String name) {
this.setName(name);
}
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
测试类:
public static void main(String[] args) {
ConcreteElementA a = new ConcreteElementA("具体元素A");
a.accept(new ConcreteVisitorA("具体访问者A"));
ConcreteElementB b = new ConcreteElementB("具体元素B");
b.accept(new ConcreteVisitorA("具体访问者A"));
ConcreteElementA c = new ConcreteElementA("具体元素A");
c.accept(new ConcreteVisitorB("具体访问者B"));
ConcreteElementB d = new ConcreteElementB("具体元素B");
d.accept(new ConcreteVisitorB("具体访问者B"));
}
测试结果:
优点
1.将数据结构和作用于数据结构上的操作解耦合,使得这些可以自由的演变。
2.符合开闭原则,增加一个新的操作将会很容易。
缺点
1.违反迪米特法则,具体元素对访问者公布细节。
2.违反了依赖倒转原则,接口依赖于细节。
使用场景
适用于对象数据结构不会发生变化,并且对该对象的操作欧不同的算法。