设计模式 State模式 机器的情况下用自己的主动性
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/26350617
状态模型给我眼前一亮的感觉啊,值得学习~
看看定义:改变一个对象的内部状态的改变行为认同,对象出现改变它的类。糊了,理一下。当对象的内部状态改变时,它的行为尾随状态的改变而改变了。看起来好像又一次初始化了一个相似的。
以下使用个样例来说明状态模式的使用方法,如今有个自己主动售货机的代码须要我们来写,状态图例如以下:
分析一个这个状态图:
a、包括4个状态(我们使用4个int型常量来表示)
b、包括3个暴露在外的方法(投币、退币、转动手柄)
c、我们须要处理每一个状态下,用户都能够触发这三个动作。
以下我们依据分析的结果。写出代码:
package com.zhy.pattern.status; /**
* 自己主动售货机
*
* @author zhy
*
*/
public class VendingMachine
{ /**
* 已投币
*/
private final static int HAS_MONEY = 0;
/**
* 未投币
*/
private final static int NO_MONEY = 1;
/**
* 售出商品
*/
private final static int SOLD = 2;
/**
* 商品售罄
*/
private final static int SOLD_OUT = 3; private int currentStatus = NO_MONEY;
/**
* 商品数量
*/
private int count = 0; public VendingMachine(int count)
{
this.count = count;
if (count > 0)
{
currentStatus = NO_MONEY;
}
} /**
* 投入硬币,不论什么状态用户都可能投币
*/
public void insertMoney()
{
switch (currentStatus)
{
case NO_MONEY:
currentStatus = HAS_MONEY;
System.out.println("成功投入硬币");
break;
case HAS_MONEY:
System.out.println("已经有硬币,无需投币");
break;
case SOLD:
System.out.println("请稍等...");
break;
case SOLD_OUT:
System.out.println("商品已经售罄,请勿投币");
break; }
} /**
* 退币,不论什么状态用户都可能退币
*/
public void backMoney()
{
switch (currentStatus)
{
case NO_MONEY:
System.out.println("您未投入硬币");
break;
case HAS_MONEY:
currentStatus = NO_MONEY;
System.out.println("退币成功");
break;
case SOLD:
System.out.println("您已经买了糖果...");
break;
case SOLD_OUT:
System.out.println("您未投币...");
break;
}
} /**
* 转动手柄购买,不论什么状态用户都可能转动手柄
*/
public void turnCrank()
{
switch (currentStatus)
{
case NO_MONEY:
System.out.println("请先投入硬币");
break;
case HAS_MONEY:
System.out.println("正在出商品....");
currentStatus = SOLD;
dispense();
break;
case SOLD:
System.out.println("连续转动也没用...");
break;
case SOLD_OUT:
System.out.println("商品已经售罄");
break; }
} /**
* 发放商品
*/
private void dispense()
{ switch (currentStatus)
{
case NO_MONEY:
case HAS_MONEY:
case SOLD_OUT:
throw new IllegalStateException("非法的状态...");
case SOLD:
count--;
System.out.println("发出商品...");
if (count == 0)
{
System.out.println("商品售罄");
currentStatus = SOLD_OUT;
} else
{
currentStatus = NO_MONEY;
}
break; } }
}
针对用户的每一个动作,我们考虑了在不论什么状态下发生,并做了一定处理。以下进行一些測试:
package com.zhy.pattern.status; public class TestTra
{
public static void main(String[] args)
{
VendingMachine machine = new VendingMachine(10);
machine.insertMoney();
machine.backMoney(); System.out.println("-----------"); machine.insertMoney();
machine.turnCrank(); System.out.println("----------压力測试-----");
machine.insertMoney();
machine.insertMoney();
machine.turnCrank();
machine.turnCrank();
machine.backMoney();
machine.turnCrank(); }
}
输出结果:
成功投入硬币
退币成功
-----------
成功投入硬币
正在出商品....
发出商品...
----------压力測试-----
成功投入硬币
已经有硬币。无需投币
正在出商品....
发出商品...
请先投入硬币
您未投入硬币
请先投入硬币
感觉还是不错的,基本实现了功能,可是有些事情是不可避免的,那就是需求的变化,如今为了提升销量,当用户每次转动手柄买商品的时候,有10%的几率赠送一瓶。
如今的状态图发生了变化,当用户转动手柄时,可能会达到一个中奖的状态:图例如以下:
假设在我们刚写的代码上直接加入。则须要在每一个动作的switch中加入推断条件,且很easy出错。所以如今我们要考虑又一次设计我们的代码,我们考虑把每一个状态写状态类。负责实如今相应动作下的行为,然后自己主动售货机在不能的状态间切换:
以下開始重构,我们如今有5种状态。相应4个动作(投币、退币、转动手柄、发出商品),以下首先定义一个状态的超类型:
package com.zhy.pattern.status.b; /**
* 状态的接口
* @author zhy
*
*/
public interface State
{
/**
* 放钱
*/
public void insertMoney();
/**
* 退钱
*/
public void backMoney();
/**
* 转动曲柄
*/
public void turnCrank();
/**
* 出商品
*/
public void dispense();
}
然后各自是每一个状态的实现:
package com.zhy.pattern.status.b; /**
* 没钱的状态
* @author zhy
*
*/
public class NoMoneyState implements State
{ private VendingMachine machine; public NoMoneyState(VendingMachine machine)
{
this.machine = machine; } @Override
public void insertMoney()
{
System.out.println("投币成功");
machine.setState(machine.getHasMoneyState());
} @Override
public void backMoney()
{
System.out.println("您未投币,想退钱?...");
} @Override
public void turnCrank()
{
System.out.println("您未投币,想拿东西么?...");
} @Override
public void dispense()
{
throw new IllegalStateException("非法状态。");
} }
package com.zhy.pattern.status.b; import java.util.Random; /**
* 已投入钱的状态
*
* @author zhy
*
*/
public class HasMoneyState implements State
{ private VendingMachine machine;
private Random random = new Random(); public HasMoneyState(VendingMachine machine)
{
this.machine = machine;
} @Override
public void insertMoney()
{
System.out.println("您已经投过币了,无需再投....");
} @Override
public void backMoney()
{
System.out.println("退币成功"); machine.setState(machine.getNoMoneyState());
} @Override
public void turnCrank()
{
System.out.println("你转动了手柄");
int winner = random.nextInt(10);
if (winner == 0 && machine.getCount() > 1)
{
machine.setState(machine.getWinnerState());
} else
{
machine.setState(machine.getSoldState());
}
} @Override
public void dispense()
{
throw new IllegalStateException("非法状态! ");
} }
package com.zhy.pattern.status.b; /**
* 售罄的状态
*
* @author zhy
*
*/
public class SoldOutState implements State
{ private VendingMachine machine; public SoldOutState(VendingMachine machine)
{
this.machine = machine;
} @Override
public void insertMoney()
{
System.out.println("投币失败。商品已售罄");
} @Override
public void backMoney()
{
System.out.println("您未投币,想退钱么?...");
} @Override
public void turnCrank()
{
System.out.println("商品售罄,转动手柄也木实用");
} @Override
public void dispense()
{
throw new IllegalStateException("非法状态!");
} }
package com.zhy.pattern.status.b; /**
* 准备出商品的状态,该状态下,不会有不论什么用户的操作
*
* @author zhy
*
*/
public class SoldState implements State
{ private VendingMachine machine; public SoldState(VendingMachine machine)
{
this.machine = machine;
} @Override
public void insertMoney()
{
System.out.println("正在出货,请勿投币");
} @Override
public void backMoney()
{
System.out.println("正在出货,没有可退的钱");
} @Override
public void turnCrank()
{
System.out.println("正在出货,请勿反复转动手柄");
} @Override
public void dispense()
{
machine.dispense();
if (machine.getCount() > 0)
{
machine.setState(machine.getNoMoneyState());
} else
{
System.out.println("商品已经售罄");
machine.setState(machine.getSoldOutState());
}
}
}
package com.zhy.pattern.status.b; /**
* 中奖的状态,该状态下不会有不论什么用户的操作
*
* @author zhy
*
*/
public class WinnerState implements State
{ private VendingMachine machine; public WinnerState(VendingMachine machine)
{
this.machine = machine;
} @Override
public void insertMoney()
{
throw new IllegalStateException("非法状态");
} @Override
public void backMoney()
{
throw new IllegalStateException("非法状态");
} @Override
public void turnCrank()
{
throw new IllegalStateException("非法状态");
} @Override
public void dispense()
{
System.out.println("你中奖了。恭喜你。将得到2件商品");
machine.dispense(); if (machine.getCount() == 0)
{
System.out.println("商品已经售罄");
machine.setState(machine.getSoldOutState());
} else
{
machine.dispense();
if (machine.getCount() > 0)
{
machine.setState(machine.getNoMoneyState());
} else
{
System.out.println("商品已经售罄");
machine.setState(machine.getSoldOutState());
} } } }
最后是自己主动售货机的代码:
package com.zhy.pattern.status.b; /**
* 自己主动售货机
*
* @author zhy
*
*/
public class VendingMachine
{
private State noMoneyState;
private State hasMoneyState;
private State soldState;
private State soldOutState;
private State winnerState ; private int count = 0;
private State currentState = noMoneyState; public VendingMachine(int count)
{
noMoneyState = new NoMoneyState(this);
hasMoneyState = new HasMoneyState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(this);
winnerState = new WinnerState(this); if (count > 0)
{
this.count = count;
currentState = noMoneyState;
}
} public void insertMoney()
{
currentState.insertMoney();
} public void backMoney()
{
currentState.backMoney();
} public void turnCrank()
{
currentState.turnCrank();
if (currentState == soldState || currentState == winnerState)
currentState.dispense();
} public void dispense()
{
System.out.println("发出一件商品...");
if (count != 0)
{
count -= 1;
}
} public void setState(State state)
{
this.currentState = state;
} //getter setter omitted ... }
能够看到,我们如今把每一个状态相应于动作的行为局部化到了状态自己的类中实现,不仅添加了扩展性并且使代码的阅读性大幅度的提高。以后再加入状态,仅仅须要针对新加入的状态的实现类,并在自己主动售货机中加入此状态就可以。
以下进行一些測试:
package com.zhy.pattern.status.b; public class Test
{
public static void main(String[] args)
{
VendingMachine machine = new VendingMachine(10);
machine.insertMoney();
machine.backMoney(); System.out.println("----我要中奖----"); machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank();
machine.insertMoney();
machine.turnCrank(); System.out.println("-------压力測试------"); machine.insertMoney();
machine.backMoney();
machine.backMoney();
machine.turnCrank();// 无效操作
machine.turnCrank();// 无效操作
machine.backMoney(); }
}
输出结果:
投币成功
退币成功
----我要中奖----
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
发出一件商品...
投币成功
你转动了手柄
你中奖了,恭喜你。将得到2件商品
发出一件商品...
发出一件商品...
-------压力測试------
投币成功
退币成功
您未投币,想退钱?...
您未投币,想拿东西么?...
您未投币,想拿东西么?...
您未投币,想退钱?...
恭喜你。又学会了一个设计模式,状态模式。最后看下状态模式的类图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
最后,欢迎大家留言~
版权声明:本文博客原创文章,博客,未经同意,不得转载。
设计模式 State模式 机器的情况下用自己的主动性的更多相关文章
- java设计模式-State模式
1.背景: MM的状态是非常不固定的,说不定刚才还非常高兴,没准一会就生气了.就跟六月的天似的,说变就变. 封装一下MM的状态:smile,cry,say:MM的状态决定了这些方法该怎么执行. 2 ...
- [Design Pattern With Go]设计模式-工厂模式
这次介绍的设计模式是工厂模式,这是一个比较常见的创建型模式.一般情况下,工厂模式分为三种:简单工厂.工厂方法和抽象工厂,下面慢慢举例介绍下. 简单工厂 考虑一个加密程序的应用场景,一个加密程序可能提供 ...
- 'adb remount'的作用是什么?在什么情况下有用?
'adb remount' 将 '/system' 部分置于可写入的模式,默认情况下 '/system' 部分是只读模式的.这个命令只适用于已被 root 的设备. 在将文件 push 到 '/sys ...
- 如何处理高并发情况下的DB插入
1. 我们需要接收一个外部的订单,而这个订单号是不允许重复的 2. 数据库对外部订单号没有做唯一性约束 3. 外部经常插入相同的订单,对于已经存在的订单则拒绝处理 对于这个需求,很简单我们会用下 ...
- 深入浅出设计模式——状态模式(State Pattern)
模式动机 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的 (stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的.当一个这样的 ...
- 设计模式---状态变化模式之state状态模式(State)
前提:状态变化模式 在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案. 典型模式 状态模式:Stat ...
- java 23种设计模式,一般情况下,常用的有哪些? 转载
原址:http://wangle.iteye.com/blog/196972 工厂模式, 工厂方法模式,单例模式, 外观(Facade)模式, 观察者(Observer)模式,桥接(Bridge)模式 ...
- C++设计模式之State模式
这里有两个例子: 1.https://www.cnblogs.com/wanggary/archive/2011/04/21/2024117.html 2.https://www.cnblogs.co ...
- 程序设计模式 —— State 状态模式
我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...
随机推荐
- HDU2586 How far away ?(LCA模板题)
题目链接:传送门 题意: 给定一棵树,求两个点之间的距离. 分析: LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)]; 在线算法:详细解说 传送门 代码例 ...
- Eclipse关闭检查
有没有发现每次操作Eclipse过后,都会有build Workspace的操作一直在后台执行,JS校验一直validate,非常卡非常受不了有木有? 有木有?以下是我个人成功的步骤,曾经试过非常多次 ...
- 解决错误 fatal error C1010: unexpected end of file while looking for precompiled head
在编译VS时候,出现fatal error C1010: unexpected end of file while looking for precompiled head. 问题详解:致命错误C10 ...
- 构建轻量级的Table View注意事项[UIKit]
參考文章来自objcio站点 一.使用ChildViewController 将Table ViewController作为Child View Controller加入到其它View Control ...
- NDK/JNI学习--进口hello-jniproject
上一篇文章,简单的设置NDK开发环境,本文通过导入C:\android-ndk-r9d\samples\hello-jni(NDK自带example)来疏通真个环境. 打开Eclipse IDE.指定 ...
- Mybatis数据操作
Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作 详细的Spring MVC框架搭配在这个连接中: Maven 工程下 Spring MVC 站点配置 (一) M ...
- Javadoc的Html文件传输chm
Javadoc的Html文件转chm 工具下载地址:http://msdn.microsoft.com/en-us/library/ms669985.aspx 两篇相关文章: MyEclipse ...
- JavaBean编程的基本思路-逻辑业务层
JavaBean是Java类别.为了实现业务逻辑层. 你是什么意思?我有一个很长的故事短:我们知道,JSP编程是Java编写的代码html文件.和JavaBean编程是Java写在另一个代码JAVA类 ...
- 使用python写appium用例
安装Python依赖 pip3.4 install nose pip3.4 install selenium pip3.4 install Appium-Python-Client 执行測试用例and ...
- Xamarin.Android 入门实例(2)之实现WCF 寄宿于IIS 的Web服务提供
1.WCF 契约 ICalculator.cs using System.ServiceModel; namespace Contracts { [ServiceContract] public in ...