java基础总结 --- enum枚举实现多路分发 石头、剪刀、布游戏示例

来源:互联网 发布:电脑怎么隐藏软件 编辑:程序博客网 时间:2024/05/29 08:30
 多路分发:
当你处理多种交互类型时,程序可能会变得相当杂乱。举例来说,如果一个系统要分析
和执行数学表达式。我们可能会声明Number.plus(Number)、Number.mulitple(Number)等等,

其中Number是各种数字对象的超类。然而,当你声明a.plus(b)时,你并不知道a或者b的确切类型,那你如何能让它们正确交互呢?

你可能从未思考过这个问题的答案。Java只支持单路分发。也就是说,如果要执行的操作包含了不止一个类型

   未知的对象时,那么Java的动态绑定机制只能处理其中一个的类型。这就无法解决我们上面提到的问题。所以,
   你必须自己来判断其他的类型,从而实现自己的动态绑定行为。
  
   解决上面问题的办法就是多路分发。多态只能发生在方法调用时,所以,如果你想使用两路分发,那么就必须有两个
   方法调用:
       第一个方法调用决定第二个未知类型,第二个方法调用决定第二个未知类型。
       要利用多路分发,程序员必须为每一个类型提供一个实际的方法调用,如果你要处理两个不同的类型体系,就需要
     为每个类型体系执行一个方法调用。
         一般而言,程序员需要由设定好的某种配置,以便一个方法调用能够引出更多的方法调用,从而能够在这个过程中
     处理多种类型。

     为了达到这种效果,我们需要与多个方法一同工作:因为每个分发都需要一个方法调用。     


下面使用多种方法实现了石头、剪刀 、布 游戏,其中就使用了enum分发机制

猜拳第一种实现:

package com.zghw.base.enumx;import static com.zghw.base.enumx.Outcome.*;import java.util.Random;/** * 使用接口和度哟个子类进行多路分发 *  * 石头、剪刀、布 游戏 *  * @author zghw * *///Item是这几种类型的接口,将会被用作多路分发interface Item {//调用Item.compete()方法开始两路分发Outcome compete(Item item);Outcome eval(Rock rock);Outcome eval(Scissors scissors);Outcome eval(Paper paper);}class Rock implements Item {//调用Item.compete()方法开始两路分发//compete()方法通过调用eval()来为另一个类型实现第二次分发。//将自身(this)作为参数调用eval(),能够调用重载过的eval()方法,//能够保留第一次分发的类型信息。当第二次分发完成时,你就能够知道两个Item对象的具体类型了。@Overridepublic Outcome compete(Item item) {return item.eval(this);}@Overridepublic Outcome eval(Rock rock) {return DRAW;}@Overridepublic Outcome eval(Scissors scissors) {return LOSE;}@Overridepublic Outcome eval(Paper paper) {return WIN;}@Overridepublic String toString() {return "Rock";}}class Scissors implements Item {@Overridepublic Outcome compete(Item item) {return item.eval(this);}@Overridepublic Outcome eval(Rock rock) {return WIN;}@Overridepublic Outcome eval(Scissors scissors) {return DRAW;}@Overridepublic Outcome eval(Paper paper) {return LOSE;}@Overridepublic String toString() {return "Scissors";}}class Paper implements Item {@Overridepublic Outcome compete(Item item) {return item.eval(this);}@Overridepublic Outcome eval(Rock rock) {return LOSE;}@Overridepublic Outcome eval(Scissors scissors) {return WIN;}@Overridepublic Outcome eval(Paper paper) {return DRAW;}@Overridepublic String toString() {return "Paper";}}public class RoShamBo1 {public static void play(Item a, Item b) {//调用Item.compete()方法开始两路分发。要判断a的类型,//分发机制会在a的时机类型的compete()内部起到分发的作用。System.out.println(a + " vs " + b + " == " + a.compete(b));}static Random random = new Random(47);public static Item newItem() {switch (random.nextInt(3)) {case 0:return new Rock();case 1:return new Scissors();case 2:return new Paper();default:return null;}}public static void main(String[] args) {for (int i = 0; i < 20; i++) {play(newItem(), newItem());}}}
猜拳第二种实现:

package com.zghw.base.enumx;public class RoShamBo {/** * 玩游戏 * @param ec * @param size */public static <T extends Enum<T> & Competitor<T>> void play(Class<T> ec,int size){for(int i=0;i<size;i++){match(Enums.next(ec),Enums.next(ec));}}/** * 比赛 * @param a * @param b */public static <T extends Enum<T> & Competitor<T>> void match(T a ,T b){System.out.println(a + " vs " + b + " == " + a.competitor(b));}}

package com.zghw.base.enumx;/** * 比赛接口 * @author zghw * * @param <T> */public interface Competitor<T> {Outcome competitor(T t);}

package com.zghw.base.enumx;import static com.zghw.base.enumx.Outcome.*;/** * 使用enum分发 * 石头、剪刀、布游戏使用enum实现 * 使用构造器来初始化每个enum实例,并以“一组”结果作为参数。 * 这二者放在一起,形成了类似查询表的结构。 * @author zghw * */public enum RoShamBo2 implements Competitor<RoShamBo2> {ROCK(DRAW,WIN,LOSE),SCISSORS(LOSE,DRAW,WIN),PAPER(WIN,LOSE,DRAW);private Outcome vrock;private Outcome vscissors;private Outcome vpaper;private RoShamBo2(Outcome rock,Outcome scissors,Outcome paper){this.vrock= rock;this.vscissors = scissors;this.vpaper = paper;}@Overridepublic Outcome competitor(RoShamBo2 t) {switch(t){default:case ROCK:return vrock;case SCISSORS:return vscissors;case PAPER:return vpaper;}}public static void main(String args[]){RoShamBo.play(RoShamBo2.class, 10);}}
猜拳最优第三种实现:

package com.zghw.base.enumx;import static com.zghw.base.enumx.Outcome.*;import java.util.EnumMap;/** * 使用EnumMap实现真正的两路分发 * 石头 、剪刀、布游戏 * @author zghw * */public enum RoShamBo3 implements Competitor<RoShamBo3> {ROCK, SCISSORS, PAPER;static EnumMap<RoShamBo3, EnumMap<RoShamBo3, Outcome>> table = new EnumMap<RoShamBo3, EnumMap<RoShamBo3, Outcome>>(RoShamBo3.class);static {//初始化表结构 就像一个表格for (RoShamBo3 rs : RoShamBo3.values()) {table.put(rs, new EnumMap<RoShamBo3, Outcome>(RoShamBo3.class));}initRow(ROCK, DRAW, WIN, LOSE);initRow(SCISSORS, LOSE, DRAW, WIN);initRow(PAPER, WIN, LOSE, DRAW);}private static void initRow(RoShamBo3 rs, Outcome vrock, Outcome vscissors,Outcome vpaper) {EnumMap<RoShamBo3, Outcome> rso = table.get(rs);rso.put(ROCK, vrock);rso.put(SCISSORS, vscissors);rso.put(PAPER, vpaper);table.put(rs, rso);}@Overridepublic Outcome competitor(RoShamBo3 t) {return table.get(this).get(t);}public static void main(String args[]) {RoShamBo.play(RoShamBo3.class, 10);}}


0 0
原创粉丝点击