首先看这样的一个情景:
西游记师徒四人,一路十万八千里。每日都需要化缘才能有吃的。
大师兄本领强大,直接去找吃的,不给就硬抢。
猪八戒好吃懒作,会去偷吃的。
沙和尚为人老实,会用自己的力气化缘。
至于唐僧则是给人讲佛法,以此来化缘。
所以,我们可以发现:对于同一件事情,或者说同一个事物,师徒四人用自己独特的方式达到目的。
对于食物,就是访问者模式中基本的数据,但是处理这个数据有着许多的方式,为了将数据与操作分离,或者为了更加方便的增加访问数据的方式,访问者模式能够很好的解决这一问题。
抽象的数据accept
具体的数据accept
抽象的访问者visit
具体的访问者visit
访问者数据分配
仿照化缘的过程,我们做一个简单的例子。
package visitor.element.abs;
import visitor.visit.abs.Visit;
public abstract class Home {
private String name;
public abstract void accept(Visit visit);
public Home(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package visitor.element.impl;
import visitor.element.abs.Home;
import visitor.visit.abs.Visit;
public class Home1 extends Home{
public Home1(String name) {
super(name);
}
@Override
public void accept(Visit visit) {
System.out.println("accept#home1");
visit.visit(this);
}
}
package visitor.element.impl;
import visitor.element.abs.Home;
import visitor.visit.abs.Visit;
public class Home2 extends Home{
public Home2(String name) {
super(name);
}
@Override
public void accept(Visit visit) {
System.out.println("accept#home2");
visit.visit(this);
}
}
package visitor.visit.abs;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
public interface Visit {
public void visit(Home1 home1);
public void visit(Home2 home2);
}
package visitor.visit.impl;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;
public class Visitor implements Visit{
@Override
public void visit(Home1 home1) {
System.out.println("visit#home1");
}
@Override
public void visit(Home2 home2) {
System.out.println("visit#home2");
}
}
package visitor.visit.impl;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;
public class Visitor1 implements Visit{
@Override
public void visit(Home1 home1) {
System.out.println("visit&home1");
}
@Override
public void visit(Home2 home2) {
System.out.println("visit&home2");
}
}
package visitor.client;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.impl.Visitor;
import visitor.visit.impl.Visitor1;
public class Main {
public static void main(String[] args) {
new Home1("home1").accept(new Visitor());
new Home2("home2").accept(new Visitor());
new Home1("home1").accept(new Visitor1());
new Home2("home2").accept(new Visitor1());
}
}
accept#home1
visit#home1
accept#home2
visit#home2
accept#home1
visit&home1
accept#home2
visit&home2
package visitor.visit.impl;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;
public class Visitor2 implements Visit{
@Override
public void visit(Home1 home1) {
System.out.println("Visitor2%"+home1.getName());
}
@Override
public void visit(Home2 home2) {
System.out.println("Visitor2%"+home2.getName());
}
}
package visitor.client;
import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.impl.Visitor;
import visitor.visit.impl.Visitor1;
import visitor.visit.impl.Visitor2;
public class Main {
public static void main(String[] args) {
new Home1("home1").accept(new Visitor());
new Home2("home2").accept(new Visitor());
new Home1("home1").accept(new Visitor1());
new Home2("home2").accept(new Visitor1());
new Home1("home1").accept(new Visitor2());
new Home2("home2").accept(new Visitor2());
}
}
accept#home1
visit#home1
accept#home2
visit#home2
accept#home1
visit&home1
accept#home2
visit&home2
accept#home1
Visitor2%home1
accept#home2
Visitor2%home2
在例子中有两个方法:
visit
accept
其中:
数据.accept(访问者)
访问者.visit(数据)
这两个方法是相反的方法,这就是双重分发。
由数据和访问者共同决定调用实际的方法。
处理与数据分离,那么可以提高组件的复用性,数据是数据,处理是处理。
对扩展开放,对修改关闭。
对于访问者模式来说,增加一个访问者是一件非常轻松的事情,只需要实现访问者的接口即可。
但是对于数据来说,增加一个数据,则要修改所有的访问者,所以,对于访问者模式,增加操作简单,增加要处理的对象困难。
可以使用迭代器模式提供访问者提供数据
以及使用组合模式扩展访问者调用具体的数据
以及在访问者模式中增加模板方法模式等等。
23种设计模式