您的位置:首页 > 编程语言 > Java开发

java编程思想恶心的enum状态机示例

2015-07-29 21:48 357 查看
下面是一个包装输入的类

package test;

import java.util.Random;

public enum Input {
NICKEL(5) , DIME(10) , QUARTER(25),DOLLAR(100),
TOOTHPASTE(200),CHIPS(75),SODA(100),SOAP(50),
ABOUT_TRANSACTION{
@Override
int amount() {
throw new RuntimeException("ABOUT_TRANSACTION") ;
}
} ,
STOP {
@Override
int amount() {
throw new RuntimeException("SHUT_DOWN.amount()") ;
}
} ;

private int value ;
private Input(){}
private Input(int value ){
this.value = value ;
}
int amount(){
return value ;
}
/**
* 随机生成输入
*/
static Random random = new Random() ;
public static Input randomSelection(){
/**
* 产生 0 ~ values().length区间内的数 , 包括0 不包括values().length
*/
return values()[random.nextInt(values().length )] ;
}
public static void main(String[] args) {
for(int i = 0 ; i < 10 ; i ++){
System.out.println(Input.randomSelection());
}
}
}


在书中(第四版)values()[random.nextInt(values().length)]写错了,后面多减了一个1,

下面是主类,真不知道作者天天在想什么,竟然能想出这样的设计 --!

package test;
import static test.Input.ABOUT_TRANSACTION;
import static test.Input.CHIPS;
import static test.Input.DIME;
import static test.Input.DOLLAR;
import static test.Input.NICKEL;
import static test.Input.QUARTER;
import static test.Input.SOAP;
import static test.Input.SODA;
import static test.Input.STOP;
import static test.Input.TOOTHPASTE;

import java.util.EnumMap;
/**
*
* 状态转换
*
* 模拟自动售货机的运行
*
*/

/**
* 该类是为了获得输入命令的类别
*/
enum Category{
MONEY(NICKEL,DIME,QUARTER,DOLLAR),
ITEM_SELECTION(TOOTHPASTE,CHIPS,SODA,SOAP),
QUIT_TRANSACTION(ABOUT_TRANSACTION),
SHUT_DOWN(STOP) ;
private Input[] values ;
private Category(Input... inputs ){
values = inputs ;
}
private static EnumMap<Input,Category> categories = new EnumMap<Input,Category>(Input.class) ;

static {
for( Category c : Category.class.getEnumConstants()){
for( Input i : c.values){
categories.put(i, c) ;
}
}
}
public static Category getCategory(Input input ){
return categories.get(input) ;
}
}
public class VendingMachine {
/**
* 模拟状态之间的转换
*
*/
private static int amount = 0 ;
private static State state = State.RESTING ;
private static Input selection = null ;
enum StateDuration {TRANSIENT}
enum State {
RESTING {
void next(Input input ){
switch(Category.getCategory(input)){
case MONEY :
amount += input.amount() ;
state = ADDING_MONEY ;
break ;
case SHUT_DOWN:
state = TERMINAL ;
break ;
default :
}
}
},
ADDING_MONEY {
void next(Input input ){
switch(Category.getCategory(input)){
case MONEY :
amount += input.amount() ;
/**
* 这里为什么不要设置state的值?
* 因为当前已经是ADDING_MONEY状态,设置了以后还是这个状态,所以不需要设置
*/
break ;
case ITEM_SELECTION :
selection = input ;
if(amount < input.amount()){
System.out.println("Insufficient money for " + selection );
}else{
state = DISPENSING ;
}
break ;
case QUIT_TRANSACTION :
state = GIVING_CHANGE ;
break ;
case SHUT_DOWN :
state = TERMINAL ;
break ;
default :
}
}
},
DISPENSING(StateDuration.TRANSIENT){
void next(){
System.out.println("Here is your " + selection ) ;
amount -= selection.amount() ;
state = GIVING_CHANGE ;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT){
void next(){
if(amount > 0 ){
System.out.println("you change : " +  amount ) ;
amount = 0 ;
}
state = RESTING ;
}
},
TERMINAL {
void output(){
System.out.println("Halted!");
}
} ;
private boolean isTransaction = false ;
void next(){

}
void next(Input input ){
throw new RuntimeException("Only call next(Input input) for non-transient states ") ;
}
void output(){System.out.println(amount);}
State(){}
State(StateDuration trans ){
this.isTransaction = true ;
}
}
public static void run(Generator<Input> gen ){
/**
* 如果在前面执行的命令中是state变为terminal,则程序结束。
* 让其变为terminal的情况为输入的命令为STOP即SHUT_DOWN类别
*/
while(state != State.TERMINAL ){
/**
* 输入随机产生命令 , 当输入的命令非transaction类型的命令时,抛出异常 ,这在默认的next中设定
* 这里的state不可能是TERMINAL,也不可能是Transaction(因为下面那个while无限循环),
* 所以永远不会执行那个会抛出异常的next方法。
*/
state.next(gen.next()) ;
/**
* 判断该命令的剩下执行是否还需要命令,Transaction是true表示下面将要执行的任务不需要再输入命令
* 所以使用无限循环将该命令执行完,然后再输出余额
*/
while(state.isTransaction){
state.next() ;
}
state.output() ;
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator() ;
run(gen) ;
}
}
class RandomInputGenerator implements Generator<Input>{
@Override
public Input next() {
return  Input.randomSelection() ;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: