下面是一个包装输入的类

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

java编程思想恶心的enum状态机示例的更多相关文章

  1. Java编程思想 (1~10)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...

  2. Java编程思想 第21章 并发

    这是在2013年的笔记整理.现在重新拿出来,放在网上,重新总结下. 两种基本的线程实现方式 以及中断 package thread; /** * * @author zjf * @create_tim ...

  3. 《Java编程思想》读书笔记(三)

    前言:三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第十一章到第十六章的内容,这一次 ...

  4. 《Java编程思想》读书笔记(四)

    前言:三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第十七章到第十八章的内容,这一次 ...

  5. 《Java编程思想》读书笔记(五)

    前言:本文是<Java编程思想>读书笔记系列的最后一章,本章的内容很多,需要细读慢慢去理解,文中的示例最好在自己电脑上多运行几次,相关示例完整代码放在码云上了,码云地址:https://g ...

  6. JAVA编程思想(第四版)学习笔记----4.8 switch(知识点已更新)

    switch语句和if-else语句不同,switch语句可以有多个可能的执行路径.在第四版java编程思想介绍switch语句的语法格式时写到: switch (integral-selector) ...

  7. 《Java编程思想》读书笔记

    前言 这个月一直没更新,就是一直在读这本<Java编程思想>,这本书可以在Java业界被传神的一本书,无论谁谈起这本书都说好,不管这个人是否真的读过这本书,都说啊,这本书很好.然后再看这边 ...

  8. 《Java编程思想第四版完整中文高清版.pdf》-笔记

    D.2.1 安插自己的测试代码 插入下述“显式”计时代码,对程序进行评测: long start = System.currentTimeMillis(); // 要计时的运算代码放在这儿 long ...

  9. Java编程思想 4th 第2章 一切都是对象

    Java是基于C++的,但Java是一种更纯粹的面向对象程序设计语言,和C++不同的是,Java只支持面向对象编程,因此Java的编程风格也是纯OOP风格的,即一切都是类,所有事情通过类对象协作来完成 ...

随机推荐

  1. AngularJS开发之_指令

    指令是什么?    指令是我们用来扩展浏览器能力的技术之一.在DOM编译期间,和HTML关联着的指令会被检测到,并且被执行.这使得指令可以为DOM指定行为,或者改变它. 1.指令的匹配模式 index ...

  2. express-3 最佳实践

    版本控制 版本控制有以下益处: 文档: 能够回溯项目的历史,回顾所做的决策及组件的开发顺序,可形成宝贵的文档.记录项目的历史是十分有价值的. 归属: 团队工作,分工清晰,节省沟通成本. 试验: 你可以 ...

  3. js-变量、作用域和内存问题,引用类型

    变量.作用域和内存问题 1.变量可能包含两种不同数据类型的值:基本类型值以及引用类型值:引用类型值保存的是内存中的对象 2.对象是按值传递的, function setName(obj){ obj.n ...

  4. 原生 js 模拟 alert 弹窗

    复制头部的 js 代码到你的 js 文件的任何地方,调用Chef.alert方法传入相应的参数即可并没有什么功能,只是一个提示的作用,可能样式比 alert 的弹窗好看点,css是写在js里的,只要你 ...

  5. 餐厅系统app7

    团队贡献分 杨子健:23 郭志豪:24 谭宇森:22 刘森松:31

  6. 餐厅app总结

    2.总结:在这几个月来说,我们发现我们能力有点不足,整一个app,没有我们想象的那么完美,所以经过我们的讨论说,我们还是需要去加强一下每一个人的能力,但是整个作业,每个人都是尽了每个人的能力. (1) ...

  7. regex: add quote for words in Notepad++

    assuming words only contain a-zA-Z0-9. search: (\<[a-zA-Z0-9]+\>) replace: "\1"

  8. 连连看[HDU1175]

    连连看 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  9. BZOJ4444 : [Scoi2015]国旗计划

    首先将坐标离散化,因为区间互不包含,可以理解为对于每个起点输出最少需要多少个战士. 将环倍长,破环成链,设$f[i]$表示区间左端点不超过$i$时右端点的最大值,可以通过$O(n)$递推求出. 那么如 ...

  10. 在ScrollView下加入的组件,不能自动扩展到屏幕高度

    ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法 在ScrollView中添加一个android:fillV ...