zoukankan      html  css  js  c++  java
  • 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() ;
        }
    }
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/caiyao/p/4687544.html
Copyright © 2011-2022 走看看