使用Enum的自动贩卖机

public enum Input {
	NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100),
	TOOTHPASTER(200), CHIPS(75), SODA(100), SOAP(50),
	ABORT_TRANSACTION{
		public int amount(){
			//Disallow
			throw new RuntimeException("ABORT.acmount()");
		}
	},
	STOP{
		// This must be the last instance
		public int amount(){
			throw new RuntimeException("SHUT_DOWN.amount()");
		}
	};
	int value;
	Input(int value){
		this.value = value;
	}
	Input(){}
//	abstract int amount();
	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)];
	}
}

 

除了2个特殊的Input实例之外,其他的Input都有相应的价格,因此在接口中

定义了amount()方法。然而, 对那两个特殊Input实例而言,调用amount()方法

并不合适,所以如果调用则抛出异常。

 

 

package enumerated;

import java.util.EnumMap;
import java.util.Iterator;

import Container.Generator;
import static enumerated.Input.*;

enum Category{
	MONEY(NICKEL, DIME, QUARTER),
	TIME_SELECTION( 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}
	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 TIME_SELECTION:
					selection = input;
					if(amount < selection.amount())
						System.out.println("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(){
				System.out.println("hers is your "+selection);
				amount -= selection.amount();
				state = GIVING_CHANGE;
			}
		},
		GIVING_CHANGE(StateDuration.TRANSIENT){
			void next(){
				if(amount > 0){
					System.out.println("Your change: "+amount);
					amount = 0;
				}
				state = RESTING;
			}
		},
		TERMINAL{
			void output(){
				System.out.println("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(){
			System.out.println(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);
	}
}
class RandomInputGenerator implements Generator<Input>{
	public Input next(){
		return Input.randomSelection();
	}
}

class FileInputGenerator implements Generator<Input>{
	private Iterator<String> input;
	public FileInputGenerator(String fileName){
//		input = new TextFile(fileName, ":").iterator();
	}
	public Input next(){
		if(!input.hasNext())
			return null;
		return Enum.valueOf(Input.class, input.next().trim());
	}
}

 

Category enum将不同类型的Input进行分组,因为可以使用categorize()方法为switch语句生成

恰当的Category实例。 使用EnumMap确保了查询时的效率和安全。

 

 

 设计缺陷: 它要求 enum State实例访问的VendingMachine属性必须声明为static,这意味着,

只能有一个VendiingMachine实例(事实上够了,因为每台机,只有一个应该程序)。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值