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

下面是一个包装输入的类

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() ;
    }
}

 

posted @ 2015-07-29 21:48  Birding  阅读(1136)  评论(0编辑  收藏  举报