过去的笔记链接
https://blog.csdn.net/u011109881/article/details/60158137

状态模式实例

用Java设计糖果机吧
大致流程:

上图中,有四种状态:没有硬币,有硬币,准备售出状态以及糖果售罄状态。而控制糖果机状态转换的则是各种动作(Action),这些动作分别是投入硬币,超时判断,转动曲柄,判断糖果决定是否售出。
GumballMachine类

public class GumballMachine {//define 4 statesprivate final int  SOLD_OUT=0;private final int  NO_COIN=1;private final int  HAS_COIN=2;private final int  START_TO_SOLD=3;int stateNow = SOLD_OUT;int count = 0;public GumballMachine(int count) {if (count > 0){stateNow = NO_COIN;}this.count = count;}//define 4 actionspublic void insertCoin(){switch (stateNow) {case SOLD_OUT:System.out.println("机器售罄,请勿投币"+getState());break;case NO_COIN://正常casestateNow = HAS_COIN;System.out.println("你投入了硬币"+getState());break;case HAS_COIN:System.out.println("你已经投过币了,无法投币"+getState());break;case START_TO_SOLD:System.out.println("请稍后投币,机器处理中"+getState());break;default:System.out.println("unknown state");break;}}public void ejectCoin(){switch (stateNow) {case SOLD_OUT:System.out.println("你没有投币"+getState());break;case NO_COIN:System.out.println("你没有投币"+getState());break;case HAS_COIN://正常casestateNow = NO_COIN;System.out.println("等待超时,退币。或者你按下了退币健"+getState());break;case START_TO_SOLD:System.out.println("你已经旋转曲柄,机器已经准备售出,无法退币"+getState());break;default:System.out.println("unknown state");break;}}public void turnCrank(){switch (stateNow) {case SOLD_OUT:System.out.println("糖果售罄,请勿操作");break;case NO_COIN:System.out.println("请先投币");break;case HAS_COIN://正常casestateNow = START_TO_SOLD;System.out.println("你转动了曲柄"+getState());break;case START_TO_SOLD:System.out.println("机器处理中,请勿操作");break;default:System.out.println("unknown state");break;}}//发放糖果public void dispense(){switch (stateNow) {case SOLD_OUT:System.out.println("请正确操作本机");break;case NO_COIN:System.out.println("请先投币");break;case HAS_COIN:System.out.println("先转动曲柄");break;case START_TO_SOLD://正常casecount --;if(count > 0){stateNow = NO_COIN;System.out.println("售出糖果"+getState());}else{stateNow = SOLD_OUT;System.out.println("售出糖果"+getState());}break;default:System.out.println("unknown state");break;}}public String getState(){switch (stateNow) {case SOLD_OUT:return (" 目前状态:糖果售罄状态");case NO_COIN:return  (" 目前状态:没有硬币状态");case HAS_COIN:return (" 目前状态:有硬币状态");case START_TO_SOLD:return (" 目前状态:准备售出状态");default:return " 目前状态:未知状态";}}
}

测试类

public class Test {public static void main(String[] args) {GumballMachine gumballMachine = new GumballMachine(3);gumballMachine.insertCoin();gumballMachine.turnCrank();gumballMachine.dispense();System.out.println("================");gumballMachine.dispense();gumballMachine.turnCrank();gumballMachine.insertCoin();System.out.println("================");gumballMachine.insertCoin();gumballMachine.turnCrank();gumballMachine.dispense();System.out.println("================");gumballMachine.insertCoin();gumballMachine.turnCrank();gumballMachine.dispense();System.out.println("================");gumballMachine.insertCoin();gumballMachine.turnCrank();gumballMachine.dispense();}
}

测试结果

你投入了硬币 目前状态:有硬币状态
你转动了曲柄 目前状态:准备售出状态
售出糖果 目前状态:没有硬币状态
================
请先投币
请先投币
你投入了硬币 目前状态:有硬币状态
================
你已经投过币了,无法投币 目前状态:有硬币状态
你转动了曲柄 目前状态:准备售出状态
售出糖果 目前状态:没有硬币状态
================
你投入了硬币 目前状态:有硬币状态
你转动了曲柄 目前状态:准备售出状态
售出糖果 目前状态:糖果售罄状态
================
机器售罄,请勿投币 目前状态:糖果售罄状态
糖果售罄,请勿操作
请正确操作本机

新加功能,中奖机制

客户希望给机器添加中奖机制,即用户每次买糖果,有10%的几率获得2个糖果.
我们可以看到GumballMachine这个类太过复杂,状态转换全都包含其中,因此我们需要做一些改变了。
1.定义状态接口

public interface State {//define 4 actionspublic void insertCoin();public void ejectCoin();public void turnCrank();public void dispense();public String getState();
}

2.重新实现GumballMachine类

public class GumballMachine {// define 4 statesState soldOutState;State hasCoinState;State noCoinState;State soldState;State winnerState;int count = 0;State stateNow = soldOutState;public GumballMachine(int count) {soldOutState = new SoldOutState(this);hasCoinState = new HasCoinState(this);noCoinState = new NoCoinState(this);soldState = new SoldState(this);winnerState = new WinnerState(this);if (count > 0) {stateNow = noCoinState;}this.count = count;}public void insertCoin() {stateNow.insertCoin();}public void ejectCoin() {stateNow.ejectCoin();}public void turnTrunk() {stateNow.turnCrank();stateNow.dispense();}void setState(State state) {stateNow = state;}void releaseBall() {if (count > 0) {count--;System.out.println("A gumball rolling out the slot...");} else {System.out.println("release ball failed");}}public State getSoldOutState() {return soldOutState;}public State getHasCoinState() {return hasCoinState;}public State getNoCoinState() {return noCoinState;}public State getSoldState() {return soldState;}public State getWinnerState() {return winnerState;}public int getCount() {return count;}public State getStateNow() {return stateNow;}}

3.实现状态类:
将原先

 private final int  SOLD_OUT=0;private final int  NO_COIN=1;private final int  HAS_COIN=2;private final int  START_TO_SOLD=3;

的设计改到类中;这样,原先我们是操作时需要判断当前状态。而现在我们是状态被固定,需要看能进行哪些操作(状态控制动作)。而且,我们不需要主动控制状态,状态由代码自动控制。

public class HasCoinState implements State {Random randomWinner = new Random(System.currentTimeMillis());GumballMachine gumballMachine;public HasCoinState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertCoin() {System.out.println("你已经投过币了");}public void ejectCoin() {System.out.println("你请求了退币");gumballMachine.setState(gumballMachine.getNoCoinState());}public void turnCrank() {System.out.println("你转动了曲柄");int winner = randomWinner.nextInt(10);if(winner ==0 && gumballMachine.getCount()>1){gumballMachine.setState(gumballMachine.getWinnerState());}else{gumballMachine.setState(gumballMachine.getSoldState());}}public void dispense() {System.out.println("请先转动曲柄");}public String getState() {return this.getClass().getName();}}
public class NoCoinState implements State {GumballMachine gumballMachine;public NoCoinState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertCoin() {System.out.println("你投币了");gumballMachine.setState(gumballMachine.getHasCoinState());}public void ejectCoin() {System.out.println("你还没有投币");}public void turnCrank() {System.out.println("你还没有投币,转杆无效");}public void dispense() {System.out.println("还没有投币,不能发放糖果");}public String getState() {return this.getClass().getName();}}
public class SoldOutState implements State {GumballMachine gumballMachine;public SoldOutState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertCoin() {System.out.println("糖果售罄,请勿操作");}public void ejectCoin() {System.out.println("糖果售罄,请勿操作");}public void turnCrank() {System.out.println("糖果售罄,请勿操作");}public void dispense() {System.out.println("糖果售罄,请勿操作");}public String getState() {return this.getClass().getName();}}
public class SoldState implements State {GumballMachine gumballMachine;public SoldState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertCoin() {System.out.println("机器处理中,请稍后");}public void ejectCoin() {System.out.println("机器已经处理,无法操作");}public void turnCrank() {System.out.println("你已经转动过曲柄了");}public void dispense() {gumballMachine.releaseBall();if(gumballMachine.count>0){gumballMachine.setState(gumballMachine.getNoCoinState());System.out.println("发放糖果");}else{System.out.println("发放糖果完毕,糖果售罄");gumballMachine.setState(gumballMachine.getSoldOutState());}}public String getState() {return this.getClass().getName();}}
public class WinnerState implements State {GumballMachine gumballMachine;public WinnerState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertCoin() {System.out.println("机器正在处理,请稍后投币");}public void ejectCoin() {System.out.println("机器正在处理,无法退币");}public void turnCrank() {System.out.println("机器正在处理,无法操作");}public void dispense() {gumballMachine.releaseBall();if(gumballMachine.getCount() == 0){gumballMachine.setState(gumballMachine.getSoldOutState());}else{System.out.println("你获得了奖励");gumballMachine.releaseBall();if(gumballMachine.getCount() == 0){gumballMachine.setState(gumballMachine.getSoldOutState());}else{gumballMachine.setState(gumballMachine.getNoCoinState());}}}public String getState() {return null;}}

4.修改测试类

public class Test {public static void main(String[] args) {GumballMachine gumballMachine = new GumballMachine(5);for(int i =0;i<5; i++){gumballMachine.insertCoin();gumballMachine.turnTrunk();System.out.println(gumballMachine.getStateNow().getState()+"---------------");}}
}

5.测试结果:

你投币了
你转动了曲柄
A gumball rolling out the slot...
发放糖果
bean.NoCoinState---------------
你投币了
你转动了曲柄
A gumball rolling out the slot...
发放糖果
bean.NoCoinState---------------
你投币了
你转动了曲柄
A gumball rolling out the slot...
发放糖果
bean.NoCoinState---------------
你投币了
你转动了曲柄
A gumball rolling out the slot...
你获得了奖励
A gumball rolling out the slot...
bean.SoldOutState---------------
糖果售罄,请勿操作
糖果售罄,请勿操作
糖果售罄,请勿操作
bean.SoldOutState---------------

状态模式的简单分析

状态模式存在几个简单部分:
context state
Context意为上下文,在这里即是GumballMachine,而state在这里就是各个state的实现类了。
可以看到GumballMachine中包含了各类状态的引用实例,而GumballMachine也存在自己当前状态的实例
GumballMachine类的操作看上去是交给了State实现类,但实际上,State中存在Context的引用,State实现类在操作时通过GumballMachine引用来控制GumballMachine状态。即下图:

Head First设计模式读书笔记九 第十章 状态模式相关推荐

  1. 大话设计模式读书笔记(十三) 状态模式

    状态模式: 状态模式定义: 状态模式(State):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像改变了其子类. 状态模式UMl类图: 状态模式Java代码实现 public class ...

  2. 步步为营 .NET 设计模式学习笔记 九、Command(命令模式)

    概述 在软件系统中,"行为请求者"与"行为实现者"通常呈现一种"紧耦合".但在某些场合,比如要对行为进行"记录.撤销/重做.事务& ...

  3. Head First设计模式读书笔记七 第八章 模板方法模式

    本文示例代码材料源自Head First设计模式 以前整理自己整理的链接: https://blog.csdn.net/u011109881/article/details/60594985 简介 模 ...

  4. Head First设计模式读书笔记四 简单工厂 工厂模式 抽象工厂模式

    本文示例代码材料源自Head First设计模式 以前整理自己整理的链接: 工厂模式 https://blog.csdn.net/u011109881/article/details/56541580 ...

  5. android工厂模式和策略模式,android 源码设计模式读书笔记(四)工厂模式和策略模式...

    把这两个一起写 因为他们两个UML的代码接口非常的相似 工厂模式代码结构图 image.png 策略模式UML image.png 在我们看完结构图后 感觉位移不同的就是Factory个Context ...

  6. 3D游戏设计读书笔记九

    3D游戏设计读书笔记九 本次作业五选一,我选择制作血条预制设计,要求如下: 分别使用 IMGUI 和 UGUI 实现 使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机 分析两种实现 ...

  7. 大话设计模式读书笔记

    主题 概要 设计模式 大话设计模式读书笔记 编辑 时间 新建 20170423 序号 参考资料 1 大话设计模式 重新看了一遍设计模式,除了一些已经特别熟悉的模式,都自己敲了一遍代码,有些豁然开朗的感 ...

  8. JavaScript设计模式读书笔记(一)= 创建型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

  9. JavaScript设计模式读书笔记(四)= 技巧型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

最新文章

  1. 【Android 内存优化】Java 引用类型 ( 强引用 | 软引用 | 弱引用 | 虚引用 )
  2. 使用 hexo-git-backup 插件备份你的 Hexo 博客
  3. (王道408考研操作系统)第二章进程管理-第一节2:进程状态及其切换
  4. 有了IDEA中的这款插件,流程图、类图轻松搞定,简直神器!
  5. android 相对布局例子代码
  6. SAP License:SAP PI(流程集成)
  7. 从零开始,CentOS6安装ghost博客
  8. 某 iOS 零点击 0day 漏洞已存在8年之久且正遭利用?苹果称正在调查并将推出补丁...
  9. Windows 查看端口使用情况
  10. 常用正则表达式匹配Antconc英文句式搭配
  11. Laravel文档梳理2、路由相关
  12. win10程序员软件列表(持续更新中...)
  13. mac升级编译器gcc方法
  14. 链表之链表的结点插入
  15. 【CSS3】变形--位移 translate()
  16. 常微分方程_一阶线性微分方程
  17. 让命令不尽然history历史纪录的一种方法
  18. java第五章:面向对象(oop)三大特性之多态
  19. NOIP备战题解集(11.10)
  20. 基于Weka的典型数据挖掘应用

热门文章

  1. cass读取dat文件_南方CASS教程+视频讲解+插件汇总,小白快速上手的测绘神器
  2. idea中artifacts、facets、modules是什么意思?
  3. 安卓 dex 通用脱壳技术研究(四)
  4. ActiveMq笔记3-AMQ高可用性理论
  5. 海洋知识科普相关调研
  6. svn://127.0.0.1/shop
  7. poj 1050(DP)
  8. lazada铺货模式的选品_Lazada的商业模式有哪些?要怎么做?
  9. 贪心算法——合并区间(Leetcode 56)
  10. C语言课后习题(28)