マルチキャスト3

4205 ワード

定数依存メソッドの使用
 
定数相関法は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()メソッドは、一連の比較を実行する2番目の配布を実行し、
動作は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);
	}
}
 
2 D配列の使用
さらに、2つの配布を実現するソリューションを簡略化することができ、各enumインスタンスには固定値(宣言の順序に基づいて)があり、
さらにordinal()法によりこの値を取得することができる.2 D配列を使用して、競合他社をマッピングできます.
競争の結果.この方法は最も簡潔で直接的な解決策を得ることができる.
 
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);
	}
}