java 枚举高级应用之状态机


 

枚举类型非常适合用来创建状态机,一个状态机通常可以拥有有限的几个状态,他通常根据输入,从一个状态进入到下一个状态。

下面是一个用枚举实现的自动售货机的例子,很简陋,但是表达清楚了意思就差不多了,也希望各位看官能指出不足之处。

 

Java代码 复制代码  收藏代码
  1. package enums;   
  2.   
  3. import java.util.Random;   
  4.   
  5. /**  
  6.  * @描述 售货机可以接收的钞票金额和所有商品的价格  
  7.  * @创建时间 2012-5-27  
  8.  * @另请参照   
  9.  */  
  10. public enum Input {   
  11.     /**五分硬币**/  
  12.     NICKEL(5),   
  13.     /**一角硬币**/  
  14.     DIME(10),   
  15.     /**两角五分**/  
  16.     QUARTER(25),   
  17.     /**一块美金**/  
  18.     DOLLAR(100),   
  19.        
  20.     /**药膏2元**/  
  21.     TOOTHPASTE(200),   
  22.     /**炸薯条75美分**/  
  23.     CHIPS(75),   
  24.     /**苏打水1元**/  
  25.     SODA(100),//   
  26.     /**肥皂5毛**/  
  27.     SOAP(50),   
  28.        
  29.     ABORT_TRANSACTION{   
  30.         public int amount(){   
  31.             throw new RuntimeException("退出时不能获取余额!");   
  32.         }   
  33.     },   
  34.     STOP{   
  35.         public int amount(){   
  36.             throw new RuntimeException("关机时不能获取余额!");   
  37.         }   
  38.     };   
  39.        
  40.     //金额   
  41.     int value;   
  42.     Input(int value){this.value = value;}   
  43.     Input(){}   
  44.     //返回该操作项的金额   
  45.     int amount(){return value;}   
  46.        
  47.     /**  
  48.      * @return 随机获取的操作  
  49.      */  
  50.     public static Input randomSelection(){   
  51.         return values()[new Random(System.nanoTime()).nextInt(values().length)];   
  52.     }   
  53. }  
package enums;

import java.util.Random;

/**
 * @描述 售货机可以接收的钞票金额和所有商品的价格
 * @创建时间 2012-5-27
 * @另请参照 
 */
public enum Input {
	/**五分硬币**/
	NICKEL(5),
	/**一角硬币**/
	DIME(10),
	/**两角五分**/
	QUARTER(25),
	/**一块美金**/
	DOLLAR(100),
	
	/**药膏2元**/
	TOOTHPASTE(200),
	/**炸薯条75美分**/
	CHIPS(75),
	/**苏打水1元**/
	SODA(100),//
	/**肥皂5毛**/
	SOAP(50),
	
	ABORT_TRANSACTION{
		public int amount(){
			throw new RuntimeException("退出时不能获取余额!");
		}
	},
	STOP{
		public int amount(){
			throw new RuntimeException("关机时不能获取余额!");
		}
	};
	
	//金额
	int value;
	Input(int value){this.value = value;}
	Input(){}
	//返回该操作项的金额
	int amount(){return value;}
	
	/**
	 * @return 随机获取的操作
	 */
	public static Input randomSelection(){
		return values()[new Random(System.nanoTime()).nextInt(values().length)];
	}
}

 

Java代码 复制代码  收藏代码
  1. package enums;   
  2. import static enums.Input.*;   
  3.   
  4. import java.util.EnumMap;   
  5. /**  
  6.  * 对自动售货机的状态分类  
  7.  */  
  8. public enum Category {   
  9.     /**放入钞票**/  
  10.     MONEY(NICKEL,DIME,QUARTER,DOLLAR),   
  11.        
  12.     /**选择商品**/  
  13.     ITEM_SELECTION(TOOTHPASTE,CHIPS,SODA,SOAP),   
  14.        
  15.     /**退出**/  
  16.     QUIT_TRANSACTION(ABORT_TRANSACTION),   
  17.        
  18.     /**关机**/  
  19.     SHUT_DOWN(STOP);   
  20.        
  21.     private Input[] values;   
  22.        
  23.        
  24.     Category(Input... types){values = types;}   
  25.        
  26.     public static EnumMap<Input, Category> categories = new EnumMap<Input, Category>(Input.class);   
  27.        
  28.     public Input[] getValues(){   
  29.         return values;   
  30.     }   
  31.     //初始化自动售货机状态集合    
  32.     static {   
  33.         for (Category  c : Category.class.getEnumConstants()) {   
  34.             for(Input input : c.values){   
  35.                 categories.put(input, c);   
  36.             }   
  37.         }   
  38.     }   
  39.        
  40.     /**返回该操作项所属状态**/  
  41.     public static Category categorize(Input input){   
  42.         return categories.get(input);   
  43.     }   
  44. }  
package enums;
import static enums.Input.*;

import java.util.EnumMap;
/**
 * 对自动售货机的状态分类
 */
public enum Category {
	/**放入钞票**/
	MONEY(NICKEL,DIME,QUARTER,DOLLAR),
	
	/**选择商品**/
	ITEM_SELECTION(TOOTHPASTE,CHIPS,SODA,SOAP),
	
	/**退出**/
	QUIT_TRANSACTION(ABORT_TRANSACTION),
	
	/**关机**/
	SHUT_DOWN(STOP);
	
	private Input[] values;
	
	
	Category(Input... types){values = types;}
	
	public static EnumMap<Input, Category> categories = new EnumMap<Input, Category>(Input.class);
	
	public Input[] getValues(){
		return values;
	}
	//初始化自动售货机状态集合 
	static {
		for (Category  c : Category.class.getEnumConstants()) {
			for(Input input : c.values){
				categories.put(input, c);
			}
		}
	}
	
	/**返回该操作项所属状态**/
	public static Category categorize(Input input){
		return categories.get(input);
	}
}

 

Java代码 复制代码  收藏代码
  1. package enums;   
  2. import static enums.Category.*;   
  3. /**  
  4.  * 自动售货机  
  5.  */  
  6. public class VendingMachine {   
  7.   
  8.     //当前运行状态   
  9.     private static State state = State.RESTING;   
  10.     //当前余额   
  11.     private static int amount = 0;   
  12.     //当前选择商品   
  13.     private static Input selection = null;   
  14.        
  15.     /**持续状态,不能做其他操作**/  
  16.     enum StateDuration{TRANSIENT}   
  17.        
  18.     /**  
  19.      * 运行状态  
  20.      */  
  21.     enum State{   
  22.         /**初始界面**/  
  23.         RESTING{   
  24.             void next(Input input){   
  25.                 switch (Category.categorize(input)) {   
  26.                 case MONEY:   
  27.                     amount += input.amount();   
  28.                     System.out.println("放入金额:"+input.amount()+"美分");   
  29.                     state = ADDING_MONEY;   
  30.                     break;   
  31.                 case SHUT_DOWN:   
  32.                     state = TERMINAL;   
  33.                     break;   
  34.                 default:   
  35.                     state = RESTING;   
  36.                     break;   
  37.                 }   
  38.             }   
  39.         },   
  40.         /**选择商品**/  
  41.         ADDING_MONEY{   
  42.             void next(Input input){   
  43.                 switch (Category.categorize(input)) {   
  44.                 case MONEY:   
  45.                     amount += input.amount();   
  46.                     System.out.println("再次放入金额:"+input.amount()+"美分,您的余额是:"+amount+"美分");   
  47.                     break;   
  48.                 case ITEM_SELECTION:   
  49.                     selection = input;   
  50.                     System.out.println("选择商品:"+input);   
  51.                     if(amount < input.amount()){   
  52.                         System.out.println("你的余额不够购买商品:"+input);   
  53.                         state = ADDING_MONEY;   
  54.                     }else state = DISPENSING;   
  55.                     break;   
  56.                 case QUIT_TRANSACTION:   
  57.                     state = GIVING_CHANGE;   
  58.                     break;   
  59.                 case SHUT_DOWN:   
  60.                     state = TERMINAL;   
  61.                     break;   
  62.                 default:   
  63.                     state = ADDING_MONEY;   
  64.                     break;   
  65.                 }   
  66.             }   
  67.         },   
  68.         /**发出商品,交易成功**/  
  69.         DISPENSING(StateDuration.TRANSIENT){   
  70.             void next(){   
  71.                 System.out.println("交易成功!请拿好您的商品:"+selection);   
  72.                 //扣除购买商品的金额   
  73.                 amount -= selection.amount();   
  74.                 state = GIVING_CHANGE;   
  75.             }   
  76.         },   
  77.         /**找零**/  
  78.         GIVING_CHANGE(StateDuration.TRANSIENT){   
  79.             void next(){   
  80.                 if(amount > 0){   
  81.                     System.out.println("请拿好您的找零:"+amount+"美分");   
  82.                     amount = 0;   
  83.                 }   
  84.                 state = TERMINAL;   
  85.             }   
  86.         },   
  87.         /**交易终止**/  
  88.         TERMINAL{   
  89.             void output(){   
  90.                 System.out.println("交易结束");   
  91.             }   
  92.         };   
  93.            
  94.         private boolean isTransient = false;   
  95.            
  96.         /**当前是否是瞬时状态(即不可以做其他操作)**/  
  97.         public boolean isTransient(){return this.isTransient;}   
  98.            
  99.         State(){}   
  100.            
  101.         State(StateDuration stateDuration){this.isTransient = true;}   
  102.            
  103.         //默认方法(在瞬时状态时做其他操作时被调用)   
  104.         void next(Input input){ System.out.println("该状态不能做其他操作!");}   
  105.         //默认方法(在非瞬时状态时不做操作时被调用)   
  106.         void next(){ System.out.println("请选择一个操作!");}   
  107.         //默认方法(查看余额)   
  108.         void output(){System.out.println("您的余额还剩:"+amount+"美分");}   
  109.     }   
  110.        
  111.     //执行一个操作   
  112.     public static void run(Input gen){   
  113.         if(state!=State.TERMINAL){   
  114.             if(state.isTransient()){   
  115.                 state.next();   
  116.             }else{   
  117.                 state.next(gen);   
  118.             }   
  119.                
  120.         }else{   
  121.             state.output();   
  122.         }   
  123.            
  124.     }   
  125.        
  126.     //测试   
  127.     public static void main(String[] args) {   
  128.         // TODO Auto-generated method stub   
  129.         int i = 0;   
  130.         while(true){   
  131.             switch (state) {   
  132.             case RESTING:   
  133.                 run(Enums.random(MONEY.getValues()));   
  134.                 break;   
  135.             case ADDING_MONEY:   
  136.                 //如果金额不足   
  137.                 if(i > 0){   
  138.                     run(Enums.random(MONEY.getValues()));   
  139.                     i = 0;   
  140.                 }else{   
  141.                     run(Enums.random(ITEM_SELECTION.getValues()));   
  142.                     i++;   
  143.                 }   
  144.                 break;   
  145.             case TERMINAL:   
  146.                 run(Input.STOP);   
  147.                 return;   
  148.             default:   
  149.                 run(null);   
  150.                 break;   
  151.             }   
  152.         }   
  153.     }   
  154. }  
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值