状态模式允许对象在内部改变时改变它的行为,对象看起来好像修改了它的类。
万能糖果公司正在研发最新的糖果机,他们的糖果机的工程师设计了如下状态转换图:
他们希望我们用java语言将这个状态转换图描述的功能实现,而且希望我们设计的有弹性一点,因为他们将来可能需要根据需求对其进行修改。
老板接到了这个活后,将这个任务交给了一位新手去设计实现,因为他想锻炼一下这位新手员工A。
员工A拿到状态转换图后,好像有点迷糊,他不知道怎么去看这个图,这时,他向组长请教:我该如何去看这个状态转换图的,哪里是开始?哪里是结束?
组长提示他说:你想象一下如果在你面前是个真实的糖果机,你要如何开始? 怎么结束?
员工A听完,醍醐灌顶,于是他梳理出来这个状态转换图的标准流程:
完整的状态流程图如下:
员工A理解的需求,他开始进行程序设计了,他不假思索,很快就给出了如下设计:
其中常量 SOLD_OUT, NO_QUARTER , HAS_QUARTER,SOLD分别标志着糖果机的四种状态。
变量 state代表着糖果机的最新状态,count代表着糖果机的糖果的数量。
方法如下:
具体的实现如下:
设计模式/src/main/java/StatePattern/first · 严家豆/设计模式 - 码云 - 开源中国 (gitee.com)
测试方法如下:
package StatePattern.first;
public class FirstTest {
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(2);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
gumballMachine.ejectQuarter();
gumballMachine.insertQuarter();
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
}
}
当他兴致勃勃的将自己的设计和实现拿给技术总监看时,技术总监却给他泼了一盆冷水:
你确定你的设计满足的客户的需求? 客户说想让我们的设计有弹性,你确定你的设计有弹性? 假如客户需要新加一种状态,你是不是还要打开GumballMachine源码进行修改呢?
致命三连问,问的员工A懵逼了。。。。。。。 看员工A在怀疑人生,总监随即给出一种解决方案: 我建议你用状态模式的角度去看这个需求,也许你会有不同的想法。
状态模式允许对象在内部改变时改变它的行为,对象看起来好像修改了它的类。
员工A看完状态模式的定义,还是很懵逼,不解的问总监: 我该如何去下手呢?
总监笑了笑,给了他一个接口:
员工A看到这个接口,回去苦思冥想,终于他悟了: 将每个状态当作一个类去设计,然后在GumballMachine去组合它进行使用,这样的话,当新增一个状态,我们就不需要去修改现有的类了,而只需要新增一个类实现State,然后再GumballMachine去修改对它的使用(而这个方式完全可以做出配置式的)即可。所以,满足了弹性设计的需求。
UML如下:
代码实现如下:
设计模式/src/main/java/StatePattern/second · 严家豆/设计模式 - 码云 - 开源中国 (gitee.com)
测试方法效果如下:
package StatePattern.second;
/**
* 状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
*/
public class SecondTest {
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(3);
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.turnCrank();
}
}
下面再根据上面的设计复习一下状态模式:
状态模式允许对象在内部改变时改变它的行为,对象看起来好像修改了它的类。