多路分发3

使用常量相关的方法

 

常量相关的方法允许我们为每个enum实例提供方法的不同实现,

这使得常量相关的方法似乎是实现多路分发的完美解决方案。

不过,通过这种方式,enum实例虽然可以具有不同的行为,

但他们任然不是类型,不能将其作为方法签名中的参数类型

来使用。最好的办法是将enum用在switch语句中

 

import static enumerated.Outcome.*;

public enum RoShamBo3 implements Competitor<RoShamBo3>{
	PAPER{
		public Outcome compete(RoShamBo3 it){
			switch(it){
			default:	// To placate the compiler
			case PAPER: return DRAW;
			case SCISSORS: return LOSE;
			case ROCK: return WIN;
			}
		}
	},
	SCISSORS{
		public Outcome compete(RoShamBo3 it){
			switch(it){
				default:
					case PAPER: return WIN;
					case SCISSORS: return DRAW;
					case ROCK: return LOSE;
			}
		}
	},
	ROCK{
		public Outcome compete(RoShamBo3 it){
			switch(it){
			default:
			case PAPER: return LOSE;
			case SCISSORS: return WIN;
			case ROCK: return DRAW;
			}
		}
	};
	
	public abstract Outcome compete(RoShamBo3 it);
	public static void main(String[] args){
		RoShamBo.play(RoShamBo3.class, 20);
	}
}

 

 

虽然这种方式可以工作, 却不合理, 如果采用RoShamBo解决方案, 在添加一个新

的类型时, 只需更少的代码, 而且更直接。


public enum RoShamBo4 implements Competitor<RoShamBo4>{
	ROCK{
		public Outcome compete(RoShamBo4 opponent){
			return compete(SCISSORS, opponent);
		}
	},
	SCISSORS{
		public Outcome compete(RoShamBo4 opponent){
			return compete(PAPER, opponent);
		}
	},
	PAPER{
		public Outcome compete(RoShamBo4 opponent){
			return compete(ROCK, opponent);
		}
	};
	
	Outcome compete(RoShamBo4 loser, RoShamBo4 opponent){
		return ((opponent == this) ? Outcome.DRAW
			: ((opponent == loser) ? Outcome.WIN
					: Outcome.LOSE));
	}
	
	public static void main(String[] args) {
		RoShamBo.play(RoShamBo4.class, 20);
	}
}

 

2个参数的compete()方法执行第二个分发,该方法执行一系列的比较,

行为类似switch语句。 这个版本的程序简单,却比较难理解。

对于一个大型系统,难以理解的代码将导致系统不够健壮。



使用EnumMap分发

import static enumerated.Outcome.*;
public 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);
	}
}
 

使用二维数组

还可以进一步简化实现两路分发的解决方案, 每个enum实例都有一个固定的值(基于声明的次序),

并且可以通过ordinal()方法取得该值。因此我们可以使用二维数组,将竞争者映射到

竞争的结果。 这种方式能够获得最简洁,最直接的解决方案

 

public enum RoShamBo6 implements Competitor<RoShamBo6>{
	PAPER, SCISSORS, ROCK;
	private static Outcome[][] tables = {
		{DRAW, LOSE, WIIN},	//PAPER
		{LOSE, WIN, DRAW},	//ROCK
		{WIN, DRAW, LOSE}, //SCISSOR
	};

	public Outcome compete(RoShamBo6 other){
		return table[this.ordinal()][other.ordinal()];
	}
	public static void main(String[] args){
		RoShamBo.play(RoShamBo6.class, 20);
	}
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值