定义
封装一些作用域某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用域这些元素的新操作。
访问者模式的角色
1:抽象访问者角色(Visitor)
该角色声明一个或者多个访问操作,定义访问者哪些接口。
public interface Visitor{
public void visit(ConcreteElement e);
public void visit(ConcreteElement2 e2);
}
2:具体访问者(ConcreteVisitor)
该角色实现抽象访问者角色中定义的各个访问操作。
public class ConcreteVisitor implements Visitor{
@Override
public void visit(ConcreteElement e){
e.operation();
}
@Override
public void visit(ConcreteElement2 e2){
e.operation();
}
}
3:抽象元素角色(Element)
该角色声明一个接受操作,接受一个访问者操作。
public abstract class Element{
public abstract void accept(Visitor visitor);
}
4:具体元素(ConcreteElement)
该角色实现抽象元素中的接受操作。
public class ConcreteElement extends Element{
public void accept(Visitor visitor){
visitor.visit(this);
}
public void operation(){
System.out.println("访问元素");
}
}
public class ConcreteElement2 extends Element{
public void accept(Visitor visitor){
visitor.visit(this);
}
public void operation(){
System.out.println("访问元素");
}
}
5:接口对象角色(ObjectStructure)
该角色可以接口中的而所有元素,如果需要,可以提供一个高层的接口让访问者可以访问每一个元素,也可以设计一个符合对象或者一个集合,如List或者Set
public class ObjectStructure{
private Vector<Element> elements;
public ObjectStructure(){
elements = new Vector<Element>();
}
public void action(Visitor visitor){
for(Element e : elements){
e.accept(visitor);
}
}
public void add(Element e){
this.elements.add(e);
}
public void createElements(){
Random random = new Random();
for(int i = 0; i< 10; i++){
if(random.nextInt(100) > 50 ){
this.add(new ConcreteElement());
}else{
this.add(new ConcreteElement2());
}
}
}
}
客户端代码:
public void Client{
ObjectStructure structure = new ObjectStructure();
structure.createElements();
Visitor visitor = new ConcreteVisitor();
structure.action(visitor);
}
优点
1:访问者模式使得增加新的操作变得很容易,增加新的操作只需增加新的访问者类。
2:将有关的行为,集中到一个访问者对象中,而不是分散到一个元素类中。
3:访问者模式可以跨等级接口访问成员类。
4:累积状态,每个单独的访问者对象都集中了相关的行为,易于系统维护。
缺点
1:增加新的元素类变得困难,每增加一个新的元素要子啊抽象访问者角色中增加一个新的操作过去。
2:破坏封装,元素对象必须暴露自己的一些操作和内部状态出来。
3:违背了依赖倒置原则,访问者依赖的是具体的元素,并不是抽象的元素。(面向程序设计五大原则https://www.jianshu.com/p/188c00f5c580)。
使用场景
1:一个对象包含很多类对象,并且接口都不同,迭代器模式不能胜任的情况下可以采用访问者模式。
2:需要访问一个对象接口中的对象进行很多不同并且不相关的操作的时候,避免操作污染类。
3:业务规则要求遍历多个不同对象的时候。(迭代器模式只能遍历同类或者同接口的数据)
参考资料:设计模式(java)
网友评论