事务的状态(状态模式)

【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 的行为;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ogm neo4j_Neo4J OGM与Quarkus

ogm neo4j在下面的视频中&#xff0c;我演示了一个使用Neo4J数据库和Neo4J OGM的Quarkus应用程序示例。 看一下GitHub上的示例项目 。 我为咖啡豆创建了一个示例域&#xff0c;其中包含我们可以查询和匹配的某些风味配置文件。 红色节点是来自某个国家/地区的咖啡豆&#xff…

什么是ThreadLocal

本文转载自 占小狼的博客前言在面试环节中&#xff0c;考察"ThreadLocal"也是面试官的家常便饭&#xff0c;所以对它理解透彻&#xff0c;是非常有必要的. 有些面试官会开门见山的提问&#xff1a; “知道ThreadLocal吗&#xff1f;”“讲讲你对ThreadLocal的理解”…

Java bytecode instruction listings

【0】README 0.1&#xff09;these contents are shiped from https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings Mnemonic Opcode (in hexadecimal) Opcode (in binary) Other bytes Stack [before]→[after] Description(no name)cb-fd these values ar…

为wmi执行例外_称之为例外?

为wmi执行例外虽然这是一个有关测试和Wiremock的Java示例&#xff0c;但它涉及一个更普遍的问题。 我们正在尝试重试Wiremock的verify方法&#xff0c;该方法可能会在我们要检查的端点被命中之前由测试调用。 在这种情况下&#xff0c;我们希望在几秒钟后循环尝试一次&#xf…

漫画:什么是MapReduce

转载自 脑洞有点大的 程序员小灰什么是MapReduce&#xff1f;MapReduce是一种编程模型&#xff0c;其理论来自Google公司发表的三篇论文&#xff08;MapReduce&#xff0c;BigTable&#xff0c;GFS&#xff09;之一&#xff0c;主要应用于海量数据的并行计算。MapReduce可以分…

orelse_可选的orElse vs orElseGet

orelseJava 8引入了一个很棒的Optional概念&#xff0c;我们在博客Java 8 Optional中进行了研究 。 因此&#xff0c;为了简要说明一下&#xff0c;Optional用于表示Optional对象或空值&#xff0c;而不是null引用。 这将有助于避免在我们尝试对空引用对象执行某些操作时发生空…

jvm(6)-java类文件结构(字节码文件)

【0】README0.1&#xff09;本文部分文字描述转自 “深入理解jvm”&#xff0c;旨在学习类文件结构 的基础知识&#xff1b;0.2&#xff09;本文荔枝以及荔枝的分析均为原创&#xff1b;0.3&#xff09;下面的截图中有附注t*编号&#xff0c;不关乎博文内容&#xff1b;0.4&am…

你可能不知道的 10 条 SQL 技巧

转载自 58沈剑 开源中国 一、一些常见的SQL实践 &#xff08;1&#xff09;负向条件查询不能使用索引 select * from order where status!0 and stauts!1 not in/not exists都不是好习惯 可以优化为in查询&#xff1a; select * from order where status in(2,3) &#x…

夜神模拟器模拟安卓测试_使用模拟进行测试

夜神模拟器模拟安卓测试如果使用正确的方法&#xff0c;模拟对象将非常有用。 我在需要驱动软件开发使用的帖子中分享了一些使用Mock Objects的经验。 在这篇文章中&#xff0c;我分享了两件事 –使用模拟进行基于合同的测试。 –用于组织模拟代码的模式。 基于合同的测试 …

java记录类型_Java中的记录类型

java记录类型于2020年3月发布的JDK 14引入了记录 &#xff08;预览语言功能&#xff09;&#xff0c;该记录提供了一种紧凑的语法来声明主要用于保存数据的类。 在记录中 &#xff0c;所有低级&#xff0c;重复且容易出错的代码都类似于构造函数&#xff0c;访问器和通用方法&a…

代理模式(多线程实现状态监控)

【-1】README-1.1&#xff09;本文部分文字描述转自“head first 设计模式”&#xff0c;旨在学习 远程代理对象 的基础知识&#xff1b;-1.2&#xff09;多线程实现糖果自动售卖机监控程序为原创&#xff1b;-1.3&#xff09;博文最后&#xff0c;转载了代理模式的定义&#…

一篇文章搞定面试中的二叉树

转载自 IOExceptioner 算法与数据结构 在上一篇介绍二叉树&#xff08; Android面试题算法之二叉树 、红黑树详细分析&#xff0c;看了都说好&#xff09;&#xff0c;没看的读者建议先去了解了解&#xff0c;接下来再给大家带来一篇关于二叉树的文章。 最近总结了一些数据结…

清洁代码_清洁单元测试

清洁代码编写使用JUnit和某些模拟库的“单元测试”测试很容易。 即使测试甚至不是单元测试并提供可疑的价值&#xff0c;它们也可能产生使某些涉众满意的代码覆盖范围。 编写单元测试&#xff08;在理论上是单元测试&#xff0c;但是比基础代码更复杂&#xff09;因此也很容易编…

jvm(6)-Class字节码文件结构总结

【0】README 0.1&#xff09;本文总结于 Clas字节码文件&#xff0c;旨在理清 Class字节码文件的大体结构&#xff1b; 【1】干货开始 对上图的分析&#xff08;Analysis&#xff09;&#xff1a;A1&#xff09;offset0 A1.1&#xff09;头四个字节为CAFEBABE&#xff1a;表示…

Android面试题算法之二叉树

转载自 qing的世界 程序员小乐文章目录 前言二叉树的递归&#xff08;深度优先&#xff09;处理二叉树的层序处理(广度优先)总结“一、前言今年可谓是跌宕起伏的一年&#xff0c;幸好结局还算是圆满。开年的时候由于和公司CTO有过节&#xff0c;被"打入冷宫"&#…

java 读取 文本块_Java文本块

java 读取 文本块文本块是JDK增强建议&#xff08; JEP 355 &#xff09;&#xff0c;可以在JDK 13和14中用作预览语言功能。它计划在JDK 15中成为永久性功能。文本块是跨越多行并且不需要的String文字。对于大多数转义序列。 动机 在标准Java字符串中嵌入XML&#xff0c;JSON…

代理模式之虚拟代理(仅了解)

【0】README0.1&#xff09;本文全文转自 “head first 设计模式”&#xff0c;旨在了解 虚拟代理动态代理&#xff1b;0.2&#xff09;晚辈我 java.swing 烂到渣&#xff0c;没有写出干货荔枝&#xff0c;抱歉&#xff1b;【1】虚拟代理简述1&#xff09;远程代理&#xff1a;…

红黑树详细分析

转载自 coolblog 算法与数据结构“一、红黑树简介红黑树是一种自平衡的二叉查找树&#xff0c;是一种高效的查找树。它是由 Rudolf Bayer 于1972年发明&#xff0c;在当时被称为对称二叉 B 树(symmetric binary B-trees)。后来&#xff0c;在1978年被 Leo J. Guibas 和 Robert…

rest api如何创建_REST:创建资源

rest api如何创建资源创建是常见的REST API操作。 在这篇文章中&#xff0c;我们将看到如何创建单个资源。 客户要求 通常&#xff0c;通过将POST请求发送到父集合资源来创建资源。 这将使用新生成的ID创建一个新的下属资源。 例如&#xff0c;对/ projects的POST请求可用于在…

java字节码指令简介(仅了解)

【0】README0.1&#xff09;本文全文转自 “深入理解jvm”&#xff0c; 旨在了解 java字节码指令 的基础知识&#xff1b;【1】写在前面1&#xff09;由于jvm 采用面向操作数栈而不是寄存器的结构&#xff0c;所以大多数的指针都不包含操作数&#xff0c;只有一个操作码&#x…