【0】README
0.1)本文部分文字描述转自 “head first设计模式”,旨在学习  事务的状态(状态模式) 的基础知识;
【1】应用场景一
1.1)还记得成都市各大高校内的米源自动售卖机吗?售卖机的主要制造商发现,只要把CPU 放入机器,可以提高销量。于是乎,它们提供了一幅自动售卖机的状态图给我们,希望我们用java 帮他实现,且代码富有弹性易于扩展(下面以米源糖果售卖机为例给出状态图);
1.2)具体实现(for downloading, please visit  https://github.com/pacosonTang/HeadFirstDesignPattern/tree/master/state_pattern_10/chapter10)
  • step1)米源售卖机实现
  • public class CandyMachine {private final static int SOLD_OUT = 0; // 售罄状态private final static int NO_QUARTER = 1; // 无币状态,QUARTER==25美分==币private final static int HAS_QUARTER = 2; // 有币状态private final static int SOLD = 3; // 售卖状态private int state = SOLD_OUT;private int count = 0;public CandyMachine(int count) {this.count = count;if(count > 0) {this.state = NO_QUARTER;}}public void insertQuarter() { // client投币请求if(state == HAS_QUARTER) {System.out.println("you can't insert another quarter.");} else if(state == NO_QUARTER) {System.out.println("you insert a quarter.");state = HAS_QUARTER;} else if(state == SOLD_OUT) {System.out.println("you can't insert a quarter for the machine is sold out.");} else if(state == SOLD) {System.out.println("please wait, we're already gibing you a candy.");}}public void ejectQuarter() { // client请求退钱if(state == HAS_QUARTER) {System.out.println("quarter returned.");state = NO_QUARTER;} else if(state == NO_QUARTER) {System.out.println("you haven't inserted a quarter.");} else if(state == SOLD_OUT) {System.out.println("you can't eject for you haven't inserted a quarter yet.");} else if(state == SOLD) {System.out.println("sorry, you already trune the crank.");}}public void turnCrank() { // client转动曲柄动作if(state == HAS_QUARTER) {System.out.println("you turned, please wait....");state = SOLD;dispense();} else if(state == NO_QUARTER) {System.out.println("you turned but there is no quarter.");} else if(state == SOLD_OUT) {System.out.println("you truned but there's no candy.");} else if(state == SOLD) {System.out.println("turning twice doesn't get you another candy.");}}private void dispense() { // 分发糖果if(state == HAS_QUARTER) {System.out.println("no candy dispensed.");} else if(state == NO_QUARTER) {System.out.println("you need to insert a quarter first.");} else if(state == SOLD_OUT) {System.out.println("no candy dispensed.");} else if(state == SOLD) {System.out.println("a candy comes rolling out the slot.");count--;if(count == 0) {System.out.println("Oops, there's no candy.");state = SOLD_OUT;} else {state = NO_QUARTER;}}}@Overridepublic String toString() {String state_str = null;switch (state) {case SOLD_OUT: state_str = "SOLD_OUT"; break;case SOLD: state_str = "SOLD"; break;case NO_QUARTER: state_str = "NO_QUARTER"; break;case HAS_QUARTER: state_str = "HAS_QUARTER"; break;}return "=== I own " + count + " candies, and stay in " + state_str + " state. ===";}
    }
  • step2)测试用例
  • public class CandyMachineTest {public static void main(String[] args) {CandyMachine cm = new CandyMachine(5);System.out.println(cm);System.out.println("====== 1st test: ======");cm.insertQuarter();cm.turnCrank();System.out.println(cm);System.out.println("====== 2nd test: ======");cm.insertQuarter();cm.ejectQuarter();//要求售卖机退钱cm.ejectQuarter();//要求售卖机第二次退钱System.out.println("====== 3rd test: ======");cm.insertQuarter();cm.ejectQuarter();cm.turnCrank();// 请求退钱后,不应该得到糖果System.out.println(cm);}
    }
  • step3)打印结果
  • === I own 5 candies, and stay in NO_QUARTER state. ===
    ====== 1st test: ======
    you insert a quarter.
    you turned, please wait....
    a candy comes rolling out the slot.
    === I own 4 candies, and stay in NO_QUARTER state. ===
    ====== 2nd test: ======
    you insert a quarter.
    quarter returned.
    you haven't inserted a quarter.
    ====== 3rd test: ======
    you insert a quarter.
    quarter returned.
    you turned but there is no quarter.
    === I own 4 candies, and stay in NO_QUARTER state. ===
【2】应用场景二(新的需求: 当曲柄被转动时,有10%的几率掉下来的是两个糖果,即有10%的可能性买一送一)
2.1)新需求下的米源售卖机实现 (for downloading, please visit  https://github.com/pacosonTang/HeadFirstDesignPattern/tree/master/state_pattern_10/chapter10_1)
  • step1)定义一个状态接口(State),在这个接口内,售卖机的每个动作有一个对应方法;
  • public abstract class State {protected String name;public abstract void insertQuarter();public abstract void ejectQuarter();public abstract void trunCrank();public abstract void dispense();public String getName() {return name;}
    }
  • step2)创建该状态接口的子类,实现售卖机的相应方法;
  • // 售罄状态
    public class SoldOutState extends State {CandyMachine machine;public SoldOutState(CandyMachine machine) {super.name = "SoldOutState";this.machine = machine;}@Overridepublic void insertQuarter() {System.out.println("you can't insert a quarter for there's no candies.");       }@Overridepublic void ejectQuarter() {System.out.println("you have not inserted a quarter.");}@Overridepublic void trunCrank() {System.out.println("you turned but there is no quarter.");}@Overridepublic void dispense() {System.out.println("you need to insert a quarter first.");     }}
    public class NoQuarterState extends State {CandyMachine machine;public NoQuarterState(CandyMachine machine) {super.name = "NoQuarterState";this.machine = machine;}@Overridepublic void insertQuarter() {System.out.println("you insert a quatter.");machine.setState(machine.getHasQuarterState());}@Overridepublic void ejectQuarter() {if(machine.getState() == machine.getHasQuarterState()) {System.out.println("returned a quarter.");machine.setState(machine.getNoQuarterState());} else {System.out.println("you have not inserted a quarter.");}}@Overridepublic void trunCrank() {System.out.println("you turned but there is no quarter.");}@Overridepublic void dispense() {System.out.println("you need to insert a quarter first.");       }
    }
    // 有币状态
    public class HasQuarterState extends State {Random random = new Random();CandyMachine machine;public HasQuarterState(CandyMachine machine) {super.name = "HasQuarterState"; this.machine = machine;}@Overridepublic void insertQuarter() {System.out.println("you can't insert another quarter.");}@Overridepublic void ejectQuarter() { // client退钱请求System.out.println("quarter returned.");machine.setState(machine.getNoQuarterState());}@Overridepublic void trunCrank() { // 有币状态下,进行几率性中奖测试System.out.println("you turned , please waiting......");int winner = random.nextInt(5);System.out.println("\nrandom winner == " + winner);if(winner == 2 && machine.getCount() > 1) {machine.setState(machine.getWinnerState());} else {machine.setState(machine.getSoldState());}}@Overridepublic void dispense() {System.out.println("no candies dispensed.");      }
    }
    
    // 售卖状态
    public class SoldState extends State {CandyMachine machine;public SoldState(CandyMachine machine) {super.name = "SoldState";this.machine = machine;}@Overridepublic void insertQuarter() {     System.out.println("please wait, we're already giving you a candy.");        }@Overridepublic void ejectQuarter() {System.out.println("sorry, you've already turned the crank.");}@Overridepublic void trunCrank() {System.out.println("turning twice doesn't get you another candy.");}@Overridepublic void dispense() {machine.releaseBall();if(machine.getCount() > 0) {machine.setState(machine.getNoQuarterState());} else {machine.setState(machine.getSoldOutState());}}
    }
  • // 中奖状态
    public class WinnerState extends State {CandyMachine machine;public WinnerState(CandyMachine machine) {this.machine = machine;}@Overridepublic void insertQuarter() {System.out.println("error.");}@Overridepublic void ejectQuarter() { // client退钱请求System.out.println("error.");}@Overridepublic void trunCrank() {System.out.println("error.");}@Overridepublic void dispense() {System.out.println("you're a winner. you get 2 candies for your quarter.");machine.releaseBall();if(machine.getCount() == 0) {machine.setState(machine.getSoldOutState());} else {machine.releaseBall();if(machine.getCount() > 0) {machine.setState(machine.getNoQuarterState());} else {System.out.println("Oops, out of candies.");machine.setState(machine.getSoldOutState());}}}
    }
  • step3)将动作委托到状态类(构造米源糖果售卖机);
  • public class CandyMachine {private State winnerState; //中奖状态private State soldOutState; // 售罄状态private State noQuarterState; // 无币状态,QUARTER==25美分==币private State hasQuarterState; // 有币状态private State soldState; // 售卖状态private State state;private int count = 0;public CandyMachine(int count) {soldOutState = new SoldOutState(this);soldState = new SoldState(this);hasQuarterState = new HasQuarterState(this);noQuarterState = new NoQuarterState(this);winnerState = new WinnerState(this);state = soldOutState;this.count = count;if(count > 0) {state = noQuarterState;}}public void insertQuarter() { // client投币请求state.insertQuarter();}public void ejectQuarter() { // client请求退钱state.ejectQuarter();}public void turnCrank() { // client转动曲柄动作state.trunCrank();state.dispense();}public void releaseBall() { // 释放糖果System.out.println("a candy comes rolling out the slot....");if(count != 0) {count--;}}public State getState() {return state;}public void setState(State state) {this.state = state;}public State getSoldOutState() {return soldOutState;}public void setSoldOutState(State soldOutState) {this.soldOutState = soldOutState;}public State getSoldState() {return soldState;}public void setSoldState(State soldState) {this.soldState = soldState;}public State getHasQuarterState() {return hasQuarterState;}public void setHasQuarterState(State hasQuarterState) {this.hasQuarterState = hasQuarterState;}public State getNoQuarterState() {return noQuarterState;}public void setNoQuarterState(State noQuarterState) {this.noQuarterState = noQuarterState;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public State getWinnerState() {return winnerState;}public void setWinnerState(State winner) {this.winnerState = winner;} @Override  public String toString() {  String state_str = null;  switch (state.getName()) {  case "SoldOutState": state_str = "SOLD_OUT"; break;  case "SoldState": state_str = "SOLD"; break;  case "NoQuarterState": state_str = "NO_QUARTER"; break;  case "HasQuarterState": state_str = "HAS_QUARTER"; break;  }  return "=== I own " + count + " candies, and stay in " + state_str + " state. ===";  }
    }

    step4)测试用例

  • public class CandyMachineTest {public static void main(String[] args) {CandyMachine cm = new CandyMachine(50);System.out.println(cm);System.out.println("====== init state ======");System.out.println(cm);// 第一次测试cm.insertQuarter();cm.turnCrank();System.out.println(cm);// 第二次测试cm.turnCrank();System.out.println(cm);// 第3次测试: 在为投币的情况下退币请求cm.ejectQuarter();System.out.println(cm);System.out.println("\n\n ====== 下面进入循环测试(中奖)随机数==2表示中奖 ======");for (int i = 0; i < 5; i++) {cm.insertQuarter();cm.turnCrank();System.out.println(cm);}}
    }
  • step5)打印结果
  • === I own 50 candies, and stay in NO_QUARTER state. ===
    ====== init state ======
    === I own 50 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......random winner == 0
    a candy comes rolling out the slot....
    === I own 49 candies, and stay in NO_QUARTER state. ===
    you turned but there is no quarter.
    you need to insert a quarter first.
    === I own 49 candies, and stay in NO_QUARTER state. ===
    you have not inserted a quarter.
    === I own 49 candies, and stay in NO_QUARTER state. ========= 下面进入循环测试(中奖,为了演示方便,我这里的中奖率为20%,且 <span style="font-family: Arial, Helvetica, sans-serif;">随机数==2表示中奖</span><span style="font-family: Arial, Helvetica, sans-serif;">) ======</span>
    you insert a quatter.
    you turned , please waiting......random winner == 2
    you're a winner. you get 2 candies for your quarter.
    a candy comes rolling out the slot....
    a candy comes rolling out the slot....
    === I own 47 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......random winner == 4
    a candy comes rolling out the slot....
    === I own 46 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......random winner == 4
    a candy comes rolling out the slot....
    === I own 45 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......random winner == 2
    you're a winner. you get 2 candies for your quarter.
    a candy comes rolling out the slot....
    a candy comes rolling out the slot....
    === I own 43 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......random winner == 0
    a candy comes rolling out the slot....
    === I own 42 candies, and stay in NO_QUARTER state. ===
    
【3】状态模式介绍
1)基本常识:策略模式和状态模式是双胞胎,在出生时才分开;
2)策略模式和状态模式:策略模式是围绕可以互换的算法来创建成功业务的;状态模式通过改变对象的内部状态来帮助对象控制自己的行为;
3)状态模式定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类;
4)因为这个模式将状态封装为独立的类,并将动作委托到代表当前状态的类,我们知道行为会随着内容部状态而改变;
【4】状态模式和策略模式的区别
4.1)状态模式:我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个。随着时间的流失,当前状态在状态对象集合中游走改变,以反映出 context内部的状态,因此,context的行为也会跟着改变;
4.2)策略模式:客户通常主动指定Context 所要组合的策略对象是哪一个。现在,固然策略模式让我们具有弹性,能够在运行时改变策略。但对于某个context对象来说,通常都只有一个 最适当的策略对象。
4.3)Conclusion:
  • C1)一般而言,我们把策略模式想成是除了继承外的一种弹性替代方案。如果你使用继承定义了一个类的行为,你将被这个行为所困住,甚至要修改他都很难。有了策略模式,你可以通过组合不同对象来改变行为;
  • C2)我们把状态模式想成是不用在 context 中放置许多条件判断的替代方案。通过将行为包装进状态对象中,你可以通过 context 内简单地修改状态对象来改变context 的行为;

事务的状态(状态模式)相关推荐

  1. mount 返回状态_状态管理模式 — Vuex如何使用?

    Extract 试想当我们在开发一个Vue应用程序时,如果在一个项目中频繁的使用组件传参的方式来同步data中的值,一旦项目结构变得复杂,管理和维护这些数据将变得十分繁琐,为此,Vue为这些被多个组件 ...

  2. RocketMQ 5.0:无状态代理模式的探索与实践

    本文作者:金吉祥, Apache RocketMQ PMC Member,阿里云智能高级技术专家 背景 首先,让我们来看下是遇到了哪些痛点问题,促使我们去探索一种无状态代理的RocketMQ新架构的: ...

  3. 理解vuex -- vue的状态管理模式

    2019独角兽企业重金招聘Python工程师标准>>> vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管 ...

  4. vuex状态管理模式:入门demo(状态管理仓)

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具 ...

  5. 设计模式学习笔记——状态(State)模式框架

    设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...

  6. 状态(State)模式

    状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它的 ...

  7. 设计模式:状态(State)模式

    设计模式之状态(State)模式 在软件开发过程中,应用程序中的有些对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态.当有状态 ...

  8. 【Vue.js】全局状态管理模式插件vuex

    文章目录 全局状态管理模式Vuex vuex是什么? 什么是"状态管理模式"? vuex的应用场景 Vuex安装 开始 核心概念 一.State 1.单一状态树 2.在 Vue 组 ...

  9. Vuex状态管理模式-M

    Vuex Vuex 是一个专为 Vue.js 开发的状态管理模式.主要是是做数据交互,父子组件传值可以很容易办到,但是兄弟组件间传值(兄弟组件下又有父子组件),页面多并且一层嵌套一层的传值,非常麻烦, ...

  10. Vuex 状态管理模式(使用)

    一.Vuex简介 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 二.使用 1.安装依赖 ...

最新文章

  1. 服务化的未来--ServiceMesh?
  2. Silverlight设计时特性的使用
  3. 边缘检测算法及各自优缺点
  4. Android服务部分总结
  5. mysql日期和时间类型_MySQL日期和时间类型
  6. 2020牛客暑期多校训练营(第二场)
  7. 前端学习(2379):调整初始目录结构
  8. 在存储过程中使用系统存储过程sp_Excute的注意事项
  9. 多个同名进程linux获取对应pid,Linux Shell根据进程名获取PID
  10. oracle从子表取出前几行数据:
  11. 象棋将帅不能碰面 java_为何象棋有“将帅不能碰面”的规则?原来这有一个不为人知的典故...
  12. MSN蠕虫Myalbum2007.zip专杀工具
  13. Qt:QtFileDialog打开文件选择对话框选择文件
  14. 智能陈桥五笔7.8试用编号是多少_学霸的学习方法,听多少都不嫌多
  15. 高数·两个重要极限练习
  16. 30个让你大呼惊艳的数据可视化作品!
  17. 油罐清洗抽吸系统设计
  18. 本地生活O2O行业已经逐渐渗透到日常生活中
  19. 投资学 U15 利率期限结构 习题解读
  20. Unity HDRP中解决抗锯齿问题

热门文章

  1. Codeforces Round #615 (Div. 3) A-F
  2. L - Two Ants Gym - 102823L
  3. 【无码专区6】球与盒子(数学线性筛)
  4. 2021牛客NOIP提高组OI赛前模拟赛第一场T2——牛牛和数组操作(区间dp)
  5. AT3857-[AGC020C]Median Sum【背包,bitset】
  6. CF741D-Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths【树上启发式合并】
  7. 【2018.4.14】模拟赛之二-ssl2392 蚂蚁【图论】
  8. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) AC(带悔贪心)
  9. [BZOJ 3173] [TJOI 2013] 最长上升子序列(splay)
  10. codeforces E. Jamie and Tree LCA+dfs序+线段树