在实际开发中也会遇到这种情况,有一个属性类E,有abcd四个属性,另外有四个类ABCD,要去访问类E,A只访问属性a,B只访问属性b,C只访问属性c,D只访问属性d。这时候访问者模式就派上用场了。
定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
结构:
- 抽象访问者:声明对每一个元素访问的行为方法,方法个数与元素个数一样
- 具体访问者:实现对每一个元素访问时产生的具体行为
- 抽象元素:声明了一个接收访问者的方法,每一个元素都要可以被访问者访问
- 具体元素:实现接收访问者的方法,通常使用访问者提供的访问钙元素的方法
- 元素结构:管理元素集合,并且可以遍历这些元素供访问者访问
适用场景:
- 对象结构比较稳定,但经常需要在此对象结构上定义新的操作
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象,也不希望在增加新操作时修改这些类
UML:
下面就是访问者模式的编码实现,以面试者来公司面试为例:
Element:
public abstract class Element {
String name;
int age;
String university;
String skill;
public Element(String name,int age,String unversity,String skill){
this.name = name;
this.age = age;
this.university = unversity;
this.skill = skill;
}
abstract void accept(Visitor visitor);
}
Interviewee(面试者):
public class Interviewee extends Element{
public Interviewee(String name,int age,String unversity,String skill) {
super(name,age,unversity,skill);
}
@Override
void accept(Visitor visitor) {
visitor.visit(this);
}
}
Visitor:
public interface Visitor {
void visit(Element inter);
}
ConcreteVisitor:
//助理只关心面试者的一些基本信息
public class Assistant implements Visitor
{
@Override
public void visit(Element inter) {
// TODO Auto-generated method stub
System.out.println("name:"+inter.name+" age:"+inter.age+" unversity:"+inter.university);
}
}
//老板关心面试者有什么技能,会做什么工作
public class BOSS implements Visitor{
@Override
public void visit(Element inter) {
// TODO Auto-generated method stub
System.out.println("name:"+inter.name+" skill:"+inter.skill);
}
}
ObjectStructure:
//模拟一个面试的过程
public class Interviewee extends Element{
public Interviewee(String name,int age,String unversity,String skill) {
super(name,age,unversity,skill);
}
@Override
void accept(Visitor visitor) {
visitor.visit(this);
}
}
Test:
public class Test {
public static void main(String[] args){
Visitor assis = new Assistant();
Visitor boss = new BOSS();
Interview in = new Interview();
System.out.println("助理了解基本信息");
in.interview(assis);
System.out.println("老板面试");
in.interview(boss);
}
}
总结:GOF如是说:大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那就是真的需要它了。在现实情况下,需要根据具体的情况来评估是否合适使用访问者模式,例如,我们的对象结构是否稳定;使用访问者模式能否优化我们的代码,而不是让代码变的更复杂。
参考:《Android源码设计模式解析与实战》