Java编程思想---枚举类型
基本enum特性
调用enum的values()方法,可以遍历enum实例,values方法返回enum实例数组,而且该数组中的元素严格保持在enum中声明时的顺序
public enum Shrubbery {
GROUND,
CRAWLING,
HANGING
}
public class EnumClass {
public static void main(String[] args) {
for (Shrubbery s : Shrubbery.values()) {
// ordinal方法返回一个int值 这是每个enum实例在声明时的次序 从 0 开始
System.out.println(s + "orginal " + s.ordinal());
System.out.println("_________________");
// enum类实现了Comparable接口 所以具有compareTo方法
System.out.println(s.compareTo(Shrubbery.CRAWLING ) + "");
System.out.println("_________________");
// 可以用 == 来比较enum实例 编译器会自动提供equal和hashcode方法
System.out.println(s == Shrubbery.CRAWLING);
System.out.println("_________________");
// getDeclaringClass方法告诉我们所属的enum类
System.out.println(s.getDeclaringClass());
System.out.println("_________________");
// name方法反复enum实例声明时的名字
System.out.println(s.name());
}
for (String s:"jdddh hfhfj jfjkfjf".split(" ")) {
// valueOf根据给定的名字返回相对应的enum实例
Shrubbery shrubbery = Enum.valueOf(Shrubbery.class,s);
System.out.println(shrubbery);
}
}
}
向enum中添加新的方法
可以向enum中添加方法,enum甚至可以有main()方法
public enum OzWitch {
// 枚举类实例能够返回对自身的描述,可以提供一个构造器,专门负责处理这个额外的信息
// 然后添加一个方法,返回这个描述信息
// 如果打算添加自己的方法,要在enum实例序列最后添加一个分号
// 同时你要先定义enum实例,再定义任何方法或者属性
// Instances must be defined first, before methods:
WEST("Miss Gulch, aka the Wicked Witch of the West"),
NORTH("Glinda, the Good Witch of the North"),
EAST("Wicked Witch of the East, wearer of the Ruby " +
"Slippers, crushed by Dorothy’s house"),
SOUTH("Good by inference, but missing");
private String description;
// Constructor must be package or private access:
private OzWitch(String description) {
this.description = description;
}
public String getDescription() { return description; }
public static void main(String[] args) {
for(OzWitch witch : OzWitch.values())
print(witch + ": " + witch.getDescription());
}
}
覆盖enum方法
public enum SpaceShip {
// 覆盖toString方法
// 以我们想要的方式来生成字符串描述信息
SCOUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP;
public String toString() {
String id = name();
String lower = id.substring(1).toLowerCase();
return id.charAt(0) + lower;
}
public static void main(String[] args) {
for(SpaceShip s : values()) {
System.out.println(s);
}
}
}
Switch中使用enum
public enum Signal {
GREEN, YELLOW, RED,
}
public class TrafficLight {
// switch中使用enum
Signal color = Signal.RED;
public void change() {
switch(color) {
// Note that you don’t have to say Signal.RED
// in the case statement:
case RED: color = Signal.GREEN;
break;
case GREEN: color = Signal.YELLOW;
break;
case YELLOW: color = Signal.RED;
break;
}
}
public String toString() {
return "The traffic light is " + color;
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
for(int i = 0; i < 7; i++) {
print(t);
t.change();
}
}
}
Values( )方法
public enum Explore {
HERE, THERE
}
public class Reflection {
// values方法从何而来?
// 利用反射机制查看一下
public static Set<String> analyze(Class<?> enumClass) {
print("----- Analyzing " + enumClass + " -----");
print("Interfaces:");
for(Type t : enumClass.getGenericInterfaces())
print(t);
print("Base: " + enumClass.getSuperclass());
print("Methods: ");
Set<String> methods = new TreeSet<String>();
for(Method m : enumClass.getMethods())
methods.add(m.getName());
print(methods);
return methods;
}
public static void main(String[] args) {
Set<String> exploreMethods = analyze(Explore.class);
Set<String> enumMethods = analyze(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(exploreMethods);
// Decompile the code for the enum:
// OSExecute.command("javap Explore");
}
}
实现,非继承
enum可以实现一个或多个接口
public enum CartoonCharacter implements Generator<CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;
private Random rand = new Random(47);
public CartoonCharacter next() {
return values()[rand.nextInt(values().length)];
}
}
//public class EnumImplementation {
//
// public static <T> void printNext(Generator<T> rg) {
// System.out.print(rg.next() + ", ");
// }
// public static void main(String[] args) {
//// Choose any instance:
// CartoonCharacter cc = CartoonCharacter.BOB;
// for(int i = 0; i < 10; i++)
// printNext(cc);
// }
//
//
//}
随机选取
利用泛型
public class Enums {
// 随机选择
// <T extends Enum<T>> 表示T是一个enum实例
// Class<T>作为参数我们就可以利用Class对象得到enum实例的数组了
private static Random rand = new Random(47);
public static <T extends Enum<T>> T random(Class<T> ec) {
return random(ec.getEnumConstants());
}
public static <T> T random(T[] values) {
return values[rand.nextInt(values.length)];
}
}
random()方法示例:
public enum Activity {
SITTING, LYING, STANDING, HOPPING,
RUNNING, DODGING, JUMPING, FALLING, FLYING
}
public class RandomTest {
public static void main(String[] args) {
for(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " " + "\n");
}
}
使用接口组织枚举
在一个接口内部,创建实现该接口的枚举
public interface Food {
// 接口内部 创建实现该接口的枚举 以此将元素分组
// 假设想用enum来表示不同的事物 同时还希望每个enum元素仍然保持food类型
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
// 对于eunum,实现接口是使其子类化的唯一办法
// 所以嵌入在food中的每个enum都实现了food接口
public class TypeFod {
public static void main(String[] args) {
Food food = Food.Appetizer.SALAD;
food = Food.MainCourse.LASAGNE;
food = Food.Dessert.GELATO;
food = Food.Coffee.CAPPUCCINO;
}
}
}
枚举中的枚举:
public enum Course {
// 创建一个 枚举的枚举
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
DESSERT(Food.Dessert.class),
COFFEE(Food.Coffee.class);
private Food[] values;
private Course(Class<? extends Food> kind) {
values = kind.getEnumConstants();
}
public Food randomSelection() {
return Enums.random(values);
}
// 每一个Course的实例都将其对应的Class对象作为构造器的参数
// 通过getEnumConstants可以获取某个Food子类的所有enum实例
//
}
public class Meal {
// 从每一个Course实例随机选择一个food 生成一份菜单
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
for (Course course : Course.values()) {
Food food = course.randomSelection();
System.out.println(food);
}
System.out.println("-------------");
}
}
}
enum嵌套在一个enum:
public enum SecurityCategory {
// 更加高效简洁的管理枚举的方法
// 将一个enum 嵌套在另一个enum里面
STOCK(Security.Stock.class), BOND(Security.Bond.class);
Security[] values;
SecurityCategory(Class<? extends Security> kind) {
values = kind.getEnumConstants();
}
// Security接口是将其包含的enum组合成一个公共类型
interface Security {
enum Stock implements Security { SHORT, LONG, MARGIN }
enum Bond implements Security { MUNICIPAL, JUNK }
}
public Security randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
SecurityCategory category =
Enums.random(SecurityCategory.class);
System.out.println(category + ": " +
category.randomSelection());
}
}
}
使用EnumSet代替标志
public enum AlarmPoints {
// enumset的元素必须来自于一个enum
// 下面的enum表示在一座大楼中
// 警报传感器的安放位置
STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,
OFFICE4, BATHROOM, UTILITY, KITCHEN
}
public class EnumSets {
// 用EnumSets来跟踪报警器的状态
public static void main(String[] args) {
EnumSet<AlarmPoints> points =
EnumSet.noneOf(AlarmPoints.class); // Empty set
points.add(BATHROOM);
print(points);
points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
points = EnumSet.allOf(AlarmPoints.class);
points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
points.removeAll(EnumSet.range(OFFICE1, OFFICE4));
print(points);
points = EnumSet.complementOf(points);
print(points);
}
}
enum超过64个元素?:
public class BigEnumSet {
// EnumSet的基础是long,一个long值有64位 而一个enum实例只需要一位 bit 表示其是否存在
// 也就是 在不超过一个long的表达能力的情况下 EnumSets可以应用于最多不超过64个元素的enum
// 所以如果元素超过了64个会发生啥?
enum Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10,
A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21,
A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32,
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43,
A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54,
A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65,
A66, A67, A68, A69, A70, A71, A72, A73, A74, A75 }
public static void main(String[] args) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
}
使用EnumMap
命令设计模式:
public interface Command {
void action();
}
public class EnumMaps {
// EnumMap 是一种特殊的Map 它要求其中的键必须来自于一个enum
public static void main(String[] args) {
EnumMap<AlarmPoints,Command> em =
new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(KITCHEN, new Command() {
public void action() { print("Kitchen fire!"); }
});
em.put(BATHROOM, new Command() {
public void action() { print("Bathroom alert!"); }
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // If there’s no value for a particular key:
em.get(UTILITY).action();
} catch(Exception e) {
print(e);
}
}
}
常量相关的方法
public enum ConstantSpecificMethod {
// Java的enum有一个有趣的特性 允许你为enum实例编写方法 从而为每个enum实例赋予不同的行为
// 要实现的话,你需要为enum定义一个或多个abstract方法 然后为每个enum实例实现该抽象方法
DATE_TIME {
String getInfo() {
return
DateFormat.getDateInstance().format(new Date());
}
},
CLASSPATH {
String getInfo() {
return System.getenv("CLASSPATH");
}
},
VERSION {
String getInfo() {
return System.getProperty("java.version");
}
};
abstract String getInfo();
public static void main(String[] args) {
for(ConstantSpecificMethod csm : values())
System.out.println(csm.getInfo());
}
}
但是我们并不能真的将enum实例作为一个类型去使用:
public enum LikeClasses {
WINKEN { void behavior() { print("Behavior1"); } },
BLINKEN { void behavior() { print("Behavior2"); } },
NOD { void behavior() { print("Behavior3"); } };
abstract void behavior();
}
public class NotClasses {
// 编译器不允许我们将一个enum实例当做class类型
// void f1(LikeClasses.WINKEN instance) {} // Nope
}
洗车的例子:
public class CarWash {
// 关于洗车的例子
// 洗车的时候提供一个选择菜单 每个选择对应一个不同的动作
// 可以将一个常量相关的方法关联到一个选择上
// 再使用一个enumset来保存客户的选择
public enum Cycle {
UNDERBODY {
void action() { print("Spraying the underbody"); }
},
WHEELWASH {
void action() { print("Washing the wheels"); }
},
PREWASH {
void action() { print("Loosening the dirt"); }
},
BASIC {
void action() { print("The basic wash"); }
},
HOTWAX {
void action() { print("Applying hot wax"); }
},
RINSE {
void action() { print("Rinsing"); }
},
BLOWDRY {
void action() { print("Blowing dry"); }
};
abstract void action();
}
EnumSet<Cycle> cycles =
EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Cycle cycle) {
cycles.add(cycle);
}
public void washCar() {
for(Cycle c : cycles)
c.action();
}
public String toString() {
return cycles.toString();
}
public static void main(String[] args) {
CarWash wash = new CarWash();
print(wash);
wash.washCar();
// Order of addition is unimportant:
wash.add(Cycle.BLOWDRY);
wash.add(Cycle.BLOWDRY); // Duplicates ignored
wash.add(Cycle.RINSE);
wash.add(Cycle.HOTWAX);
print(wash);
wash.washCar();
}
}
覆盖常量相关方法:
public enum OverrideConstantSpecific {
// 是否可以覆盖常量相关的方法呢? 当然可以
NUT, BOLT,
WASHER {
void f() { print("Overridden method"); }
};
void f() { print("default behavior"); }
public static void main(String[] args) {
for(OverrideConstantSpecific ocs : values()) {
printnb(ocs + ": ");
ocs.f();
}
}
}
使用enum的责任链
public class Mail {
// 责任链设计模式
// 程序员以不同的方式来解决一个问题 然后将它们链接到一起
// 以一个邮局的模型为例,邮局需要以尽可能通用的方式来处理每一封邮件,并且要不断尝试处理邮件 直到该邮件被认定为一封死信
// 邮件的每个关键特征都可以用enum来表示 程序将随机生成Mail对象
// The NO’s lower the probability of random selection:
enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}
enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4}
enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5}
GeneralDelivery generalDelivery;
Scannability scannability;
Readability readability;
Address address;
ReturnAddress returnAddress;
static long counter = 0;
long id = counter++;
public String toString() { return "Mail " + id; }
public String details() {
return toString() +
", General Delivery: " + generalDelivery +
", Address Scanability: " + scannability +
", Address Readability: " + readability +
", Address Address: " + address +
", Return address: " + returnAddress;
}
// Generate test Mail:
// 负责随机的创建用于测试的邮件
public static Mail randomMail() {
Mail m = new Mail();
m.generalDelivery= Enums.random(GeneralDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.address = Enums.random(Address.class);
m.returnAddress = Enums.random(ReturnAddress.class);
return m;
}
public static Iterable<Mail> generator(final int count) {
return new Iterable<Mail>() {
int n = count;
public Iterator<Mail> iterator() {
return new Iterator<Mail>() {
public boolean hasNext() { return n-- > 0; }
public Mail next() { return randomMail(); }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
};
}
}
public class PostOffice {
enum MailHandler {
GENERAL_DELIVERY {
boolean handle(Mail m) {
switch(m.generalDelivery) {
case YES:
print("Using general delivery for " + m);
return true;
default: return false;
}
}
},
MACHINE_SCAN {
boolean handle(Mail m) {
switch(m.scannability) {
case UNSCANNABLE: return false;
default:
switch(m.address) {
case INCORRECT: return false;
default:
print("Delivering "+ m + " automatically");
return true;
}
}
}
},
VISUAL_INSPECTION {
boolean handle(Mail m) {
switch(m.readability) {
case ILLEGIBLE: return false;
default:
switch(m.address) {
case INCORRECT: return false;
default:
print("Delivering " + m + " normally");
return true;
}
}
}
},
RETURN_TO_SENDER {
boolean handle(Mail m) {
switch(m.returnAddress) {
case MISSING: return false;
default:
print("Returning " + m + " to sender");
return true;
}
}
};
abstract boolean handle(Mail m);
}
static void handle(Mail m) {
for(MailHandler handler : MailHandler.values())
if(handler.handle(m))
return;
print(m + " is a dead letter");
}
public static void main(String[] args) {
for(Mail mail : Mail.generator(10)) {
print(mail.details());
handle(mail);
print("*****");
}
}
}
使用enum的状态机
public enum Input {
NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100),
TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50),
ABORT_TRANSACTION {
public int amount() { // Disallow
throw new RuntimeException("ABORT.amount()");
}
},
STOP { // This must be the last instance.
public int amount() { // Disallow
throw new RuntimeException("SHUT_DOWN.amount()");
}
};
int value; // In cents
Input(int value) { this.value = value; }
Input() {}
int amount() { return value; }; // In cents
static Random rand = new Random(47);
public static Input randomSelection() {
// Don’t include STOP:
return values()[rand.nextInt(values().length - 1)];
}
}
public enum Category {
MONEY(NICKEL, DIME, QUARTER, DOLLAR),
ITEM_SELECTION(TOOTHPASTE, CHIPS, SODA, SOAP),
QUIT_TRANSACTION(ABORT_TRANSACTION),
SHUT_DOWN(STOP);
private Input[] values;
Category(Input... types) { values = types; }
private static EnumMap<Input,Category> categories =
new EnumMap<Input,Category>(Input.class);
static {
for(Category c : Category.class.getEnumConstants())
for(Input type : c.values)
categories.put(type, c);
}
public static Category categorize(Input input) {
return categories.get(input);
}
}
public class VendingMachine {
private static State state = State.RESTING;
private static int amount = 0;
private static Input selection = null;
enum StateDuration { TRANSIENT } // Tagging enum
enum State {
RESTING {
void next(Input input) {
switch(Category.categorize(input)) {
case MONEY:
amount += input.amount();
state = ADDING_MONEY;
break;
case SHUT_DOWN:
state = TERMINAL;
default:
}
}
},
ADDING_MONEY {
void next(Input input) {
switch(Category.categorize(input)) {
case MONEY:
amount += input.amount();
break;
case ITEM_SELECTION:
selection = input;
if(amount < selection.amount())
print("Insufficient money for " + selection);
else state = DISPENSING;
break;
case QUIT_TRANSACTION:
state = GIVING_CHANGE;
break;
case SHUT_DOWN:
state = TERMINAL;
default:
}
}
},
DISPENSING(StateDuration.TRANSIENT) {
void next() {
print("here is your " + selection);
amount -= selection.amount();
state = GIVING_CHANGE;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
void next() {
if(amount > 0) {print("Your change: " + amount);
amount = 0;
}
state = RESTING;
}
},
TERMINAL { void output() { print("Halted"); } };
private boolean isTransient = false;
State() {}
State(StateDuration trans) { isTransient = true; }
void next(Input input) {
throw new RuntimeException("Only call " +
"next(Input input) for non-transient states");
}
void next() {
throw new RuntimeException("Only call next() for " +
"StateDuration.TRANSIENT states");
}
void output() { print(amount); }
}
static void run(Generator<Input> gen) {
while(state != State.TERMINAL) {
state.next(gen.next());
while(state.isTransient)
state.next();
state.output();
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
if(args.length == 1)
gen = new FileInputGenerator(args[0]);
run(gen);
}
}
多路分发
“剪刀石头布游戏”
public enum Outcome {
// 结果
WIN,
LOSE,
DRAW
}
public class Paper implements Item{
// 对应剪刀石头布 中的 布
@Override
public Outcome compete(Item item) {
return item.eval(this);
}
// 一样肯定平局
@Override
public Outcome eval(Paper paper) {
return Outcome.DRAW;
}
//
@Override
public Outcome eval(Scissors scissors) {
return Outcome.WIN;
}
@Override
public Outcome eval(Rock rock) {
return Outcome.LOSE;
}
@Override
public String toString() {
return "Paper{}";
}
}
public class Rock implements Item{
// 对应剪刀石头布 中的 石头
@Override
public Outcome compete(Item item) {
return item.eval(this);
}
@Override
public Outcome eval(Paper paper) {
return Outcome.WIN;
}
@Override
public Outcome eval(Scissors scissors) {
return Outcome.LOSE;
}
@Override
public Outcome eval(Rock rock) {
return Outcome.DRAW;
}
@Override
public String toString() {
return "Rock{}";
}
}
public class Scissors implements Item{
// // 对应剪刀石头布 中的 剪刀
@Override
public Outcome compete(Item item) {
return item.eval(this);
}
@Override
public Outcome eval(Paper paper) {
return Outcome.LOSE;
}
@Override
public Outcome eval(Scissors scissors) {
return Outcome.DRAW;
}
@Override
public Outcome eval(Rock rock) {
return Outcome.WIN;
}
@Override
public String toString() {
return "Scissors{}";
}
}
public interface Item {
Outcome compete(Item item);
Outcome eval(Paper paper);
Outcome eval(Scissors scissors);
Outcome eval(Rock rock);
}
public class RoShamBo1 {
static final int SIZE = 20;
private static Random random = new Random(47);
// 随机出 剪刀石头布
public static Item newItem(){
switch (random.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) {
// 随机比赛 20次
for (int i = 0; i < SIZE; i++) {
match(newItem(),newItem());
}
}
}
使用enum分发
public enum RoShamBo2 implements Competitor<RoShamBo2>{
// 使用enum分发
PAPER(DRAW, LOSE, WIN),
SCISSORS(WIN, DRAW, LOSE),
ROCK(LOSE, WIN, DRAW);
private Outcome vPAPER, vSCISSORS, vROCK;
RoShamBo2(Outcome paper,Outcome scissors,Outcome rock) {
this.vPAPER = paper;
this.vSCISSORS = scissors;
this.vROCK = rock;
}
public Outcome compete(RoShamBo2 it) {
switch(it) {
default:
case PAPER: return vPAPER;
case SCISSORS: return vSCISSORS;
case ROCK: return vROCK;
}
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo2.class, 20);
}
}
使用常量相关的方法
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);
}
}
简化:
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);
}
}
使用EnumMap分发
public enum RoShamBo5 implements Competitor<RoShamBo5> {
// 使用EnumMap分发
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 enum RoShamBo6 implements Competitor<RoShamBo6> {
// 用数组实现分发
PAPER, SCISSORS, ROCK;
private static Outcome[][] table = {
{ DRAW, LOSE, WIN }, // PAPER
{ WIN, DRAW, LOSE }, // SCISSORS
{ LOSE, WIN, DRAW }, // ROCK
};
public Outcome compete(RoShamBo6 other) {
return table[this.ordinal()][other.ordinal()];
}
public static void main(String[] args) {
RoShamBo.play(RoShamBo6.class, 20);
}
}
网友评论