首页 > 代码库 > 访问者模式
访问者模式
访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
男女对比这么多的原因是因为人类在性别上就只有男人和女人两类。
如果人类的性别不止男女,而是可能有多种性别,那就意味着“状态”类中的抽象方法就不可能稳定了,每加一种类别,就需要在状态类和它的所有下属类中都增加一个方法,就不符合开放-封闭原则。
访问者模式适用:适用于数据结构(男女性别)相对稳定的系统。
它把数据结构(男女性别)和作用于结构上的操作(状态)之间耦合脱开,使得操作集合可以相对自由地演化。
访问者模式的目的:是要把处理(状态)从数据结构(男女性别)分离出来。很多系统可以按照算法(状态)和数据结构(男女性别)分开,如果这样的系统有比较稳定的数据结构(男女性别),又有易于变化的算法(状态)的话,使用访问者模式就是比较合适的。因为访问者模式使得算法(状态)操作的增加变得容易。反之,如果这样的系统的数据结构对象(男女性别)易于变化,经常要有新的数据对象增加进来,就不适合使用访问者模式。
其实访问者模式的优点就是增加新的操作(状态)很容易,因为增加新的操作(状态)就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中(某个状态对象)。
访问者模式缺点:其实就是使增加新的数据结构(人的性别除了固定的男女,如果还有别的性别)变得困难了。
Person类
package visitor; public abstract class Person { //获得"visitor"对象的 public abstract void accept(Visitor visitor); }
ManPerson类
package visitor; public class ManPerson extends Person { @Override public void accept(Visitor visitor) { /** * 双分派技术:首先在客户端程序中将具体状态作为参数传递给“男人”类,完成了一次分派。 * 然后“男人”类调用作为参数的“具体状态”中的方法“男人反应”,同时将自己(this)作为参数传递进去。这便完成了第二次分派。 * 双分派意味着得到执行的操作决定于请求的种类(visitor)和两个接受者(男人、女人)的类型。 * 接受方法就是一个双分派的操作,它得到执行的操作不仅决定于“状态”类的具体状态,还决定于它访问的“人”的类别。 */ visitor.getManResponse(this); } }
WomanPerson类
package visitor; public class WomanPerson extends Person { @Override public void accept(Visitor visitor) { visitor.getWomanResponse(this); } }
Visitor类
package visitor; /** * 访问类,状态类 * @author 煞笔 * */ public abstract class Visitor { //获取男人的反应 public abstract void getManResponse(Person p); //获取女人的反应 public abstract void getWomanResponse(Person p); }
SuccessVisitor类
package visitor; /** * 成功访问类,成功状态类 * @author 煞笔 * */ public class SuccessVisitor extends Visitor { @Override public void getManResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"背后多半有个伟大的女人"); } @Override public void getWomanResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"背后多半有个不成功的女人"); } }
FailVisitor类
package visitor; /** * 失败访问类,失败状态类 * @author 煞笔 * */ public class FailVisitor extends Visitor { @Override public void getManResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"借酒浇愁"); } @Override public void getWomanResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"哭的死去活来"); } }
LoveVisitor类
package visitor; /** * 恋爱访问类,恋爱状态类 * @author 煞笔 * */ public class LoveVisitor extends Visitor { @Override public void getManResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"不懂装懂"); } @Override public void getWomanResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"懂也假装不懂"); } }
MarryVisitor类
package visitor; /** * 结婚访问类,结婚状态类 * @author 煞笔 * */ public class MarryVisitor extends Visitor { @Override public void getManResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"婚姻禁锢"); } @Override public void getWomanResponse(Person p) { System.out.println("性别"+p.getClass().getSimpleName()+",状态:"+this.getClass().getSimpleName()+"婚姻稳定"); } }
ObjectStructure类
package visitor; import java.util.ArrayList; import java.util.List; /** * 对象结构类,能枚举它的元素,可以提供一个高层的接口,以允许访问者访问它的元素。(数据结构稳定的,而且能够枚举出来) * 例如:人类就分两种:男人和女人 * @author 煞笔 * */ public class ObjectStructure { public List<Person> list = new ArrayList<Person>(); public void attch(Person p){ list.add(p); } public void remove(Person p){ list.remove(p); } public void display(Visitor visitor){ for(Person p:list){ p.accept(visitor); } } }
Business
package visitor; public class Business { public static void main(String[] args) { ObjectStructure obj = new ObjectStructure(); obj.attch(new ManPerson()); obj.attch(new WomanPerson()); Visitor visitor = new SuccessVisitor(); obj.display(visitor); visitor = new FailVisitor(); obj.display(visitor); visitor = new LoveVisitor(); obj.display(visitor); visitor = new MarryVisitor(); obj.display(visitor); } }
访问者模式