首页 > 代码库 > 访问者模式-2

访问者模式-2

接  3.5 访问者模式(5.11) 

访问者模式的核心是解决a.foo(b)的双分派问题。所以还是给出一个简单的例子。好人打贱人。好人有南拳、北腿类,贱人有鬼子、棒子、B2等。

访问者模式中客户Test会创建各种各样的对象,只调用一个方法 ”好人"的 打(贱人 j) 方法。


/**
 * 
 * @author yqj2065
 * @version 2014.9
 */
public abstract class 好人{
    //测试目标 好人 .打(贱人),应该能够找到2*3个方法体
    public abstract void 打(贱人 j);    
    abstract void 打JP();
    abstract void 打Bar();
    abstract void 打B2();
}
abstract class 贱人{
    public abstract void cmd(好人 x);// Command
}

按照采用的技术不同,好人中可以使用重载(程序中就需要用instanceof)、可以使用不同方法名(本例采用的方式)——这些方法由贱人们调用,Test不需要知道,所以采用默认访问控制。注意:不同于Gof,visitXx()中没有参数

关键点:不同于GoF,Visitor为客户提供了一个统一的访问接口 打(贱人 j) 

贱人之所以贱,在GoF中它的方法名不是command而是accept。这个方法的目的是将重载的打(贱人 j) 方法区分开来,转换成 x.打JP()等。

import static tool.Print.*;

public class 南拳 extends 好人{
    @Override public void 打(贱人 j){
        j.cmd(this);
    }
    @Override void 打JP(){  pln("南拳.打JP()"); }
    @Override void 打Bar(){ pln("南拳.打Bar()");}
    @Override void 打B2(){  pln("南拳.打B2()"); }
}
class JP extends 贱人{
    @Override public void cmd(好人 x){//命令
        x.打JP();
    }
}//其他的北腿、棒子、B2 略
测试:

    public static void test访问者(){
        好人 m1 = (好人)God.create("3-30-q");//南拳对象
        好人 m2 = (好人)God.create("3-30-t");//北腿对象
        贱人 a = (贱人)God.create("3-30-jp");
        贱人 b = (贱人)God.create("3-30-bar");
        贱人 c = (贱人)God.create("3-30-b2");
        // x .打(y);
        m1.打(a);
        m1.打(b);
        m1.打(c);
        m2.打(a);
        m2.打(b);
        m2.打(c);
    }
输出:
南拳.打JP()
南拳.打Bar()
南拳.打B2()
北腿.打JP()
北腿.打Bar()
北腿.打B2()

现在,好人中增加刀客类,按照南拳的样子写一个。测试代码创建一个刀客对象m3,m3.打(a);m3.打(b);m3.打(c);

输出:

南拳.打JP()....
北腿.打B2()
刀客.打JP()
刀客.打Bar()
刀客.打B2()

与抽象工厂类似,增加一个好人的子类很方便;增加一个贱人的子类,好人的类层次都需要修改。


如果愿意,也可以用一个ArrayList把贱人对象放进去,把贱人叫作Element,JP是具体的元素...

这就是访问者模式的基本内容。


访问者模式-2