• 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() ;
        }
    }
  • 相关阅读:
    事后诸葛亮
    OVS常用命令
    阿里云部署杂记
    Alpha冲刺总结
    测试随笔
    Alpha冲刺集合
    项目Alpha冲刺Day12
    项目Alpha冲刺Day11
    项目Alpha冲刺Day10
    MySQL修改密码
  • 原文地址:https://www.cnblogs.com/caiyao/p/4687544.html
Copyright © 2020-2023  润新知