java实现多路分发

来源:互联网 发布:淘宝里怎么贷款 编辑:程序博客网 时间:2024/06/15 05:27
   多路分发就是指在调用a.plus(b),a和b都不知道确切类型,也能让他们正常交互。
    如果想使用两路分发,那么必须有两个方法调用,第一个方法调用决定第一个未知类型,第二个方法调用决定第二个未知类型。要利用多路分发,程序员必须为每一个类型提供给一个实际的方法调用。一般而言,程序员需要设定好某种配置,以便一个方法调用能够引出更多的方法调用,从而能在这个过程中处理多个类型。

   下面是个“石头 剪刀 布”(RoShamBo)游戏的例子 (from: thinking in java):

public enum Outcome { WIN, LOSE, DRAW } ///:~interface Item {Outcome compete(Item it);Outcome eval(Paper p);Outcome eval(Scissors s);Outcome eval(Rock r);}class Paper implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return DRAW;}public Outcome eval(Scissors s) {return WIN;}public Outcome eval(Rock r) {return LOSE;}public String toString() {return "Paper";}}class Scissors implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return LOSE;}public Outcome eval(Scissors s) {return DRAW;}public Outcome eval(Rock r) {return WIN;}public String toString() {return "Scissors";}}class Rock implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return WIN;}public Outcome eval(Scissors s) {return LOSE;}public Outcome eval(Rock r) {return DRAW;}public String toString() {return "Rock";}}public class RoShamBo1 {static final int SIZE = 20;private static Random rand = new Random(47);public static Item newItem() {switch (rand.nextInt(3)) {default:case 0:return new Scissors();case 1:return new Paper();case 2:return new Rock();}}public static void match(Item a, Item b) {System.out.println(a + " vs. " + b + ": " + a.compete(b));}public static void main(String[] args) {for (int i = 0; i < SIZE; i++)match(newItem(), newItem());}} 

RoshamBol.match()有2个item参数,通关过Item.compete()方法开始2路分发,要判定a的类型,分发机制会在a的实际类型的compete()内部起到分发作用。compete()方法通关过eval()来为另一个类型实现第二次分发, 将自身(this)作为参数调用eval(),能够调用重载过的eval()方法,这能够保留第一次分发的类型信息,第二次分发完成时,就能知道两个Item对象的具体类型了。



使用EnumMap分发:


enum RoShamBo5 implements Competitor<RoShamBo5> {PAPER, SCISSORS, ROCK;static EnumMap<RoShamBo5, EnumMap<RoShamBo5, Outcome>> table = new EnumMap<RoShamBo5, EnumMap<RoShamBo5, Outcome>>(RoShamBo5.class);static {for (RoShamBo5 it : RoShamBo5.values())table.put(it, new EnumMap<RoShamBo5, Outcome>(RoShamBo5.class));initRow(PAPER, DRAW, LOSE, WIN);initRow(SCISSORS, WIN, DRAW, LOSE);initRow(ROCK, LOSE, WIN, DRAW);}static void initRow(RoShamBo5 it, Outcome vPAPER, Outcome vSCISSORS,Outcome vROCK) {EnumMap<RoShamBo5, Outcome> row = RoShamBo5.table.get(it);row.put(RoShamBo5.PAPER, vPAPER);row.put(RoShamBo5.SCISSORS, vSCISSORS);row.put(RoShamBo5.ROCK, vROCK);}public Outcome compete(RoShamBo5 it) {return table.get(this).get(it);}public static void main(String[] args) {RoShamBo.play(RoShamBo5.class, 20);}} public class RoShamBo {public static <T extends Competitor<T>> void match(T a, T b) {System.out.println(a + " vs. " + b + ": " + a.compete(b));}public static <T extends Enum<T> & Competitor<T>> void play(Class<T> rsbClass, int size) {for (int i = 0; i < size; i++)match(Enums.random(rsbClass), Enums.random(rsbClass));}}


原创粉丝点击