设计模式 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++实现,你不一 ... 
随机推荐
- jquery validation remote depends 验证触发条件
			背景: 1:简介页面的变化: 2:邮箱不能反复 改动页面,邮箱默认带出,但字段上带有remote验证.不能反复,焦点由邮箱输入框失去时.会默认触发remote验证. 介绍完成 watermark/2/ ... 
- IIS架构与HTTP请求处理流程
			IIS架构与HTTP请求处理流程 Windows操作系统中的IIS负责提供互联网服务,一台运行了IIS的计算机可以看成是一台Web服务器. Windows XP SP2 中IIS主版本号为5,Wind ... 
- Maven + Jetty + Jersey搭建RESTful服务
			IntelliJ IDEA + Maven + Jetty + Jersey搭建RESTful服务 本文参考以下内容: 使用Jersey实现RESTful风格的webservice(一) Starti ... 
- JDBC与反射
			什么是JDBC Java定义了一套关于连接使用数据库的规范(接口)叫做JDBC,许多数据库厂商实现了这个规范,所以我们可以通过Java提供的接口编程,使得我们更换数据库的时候不用修改原来的代码,只需要 ... 
- windows phone 7 定位(获取经纬度),然后找到经纬度所在的位置(城市信息)
			原文:windows phone 7 定位(获取经纬度),然后找到经纬度所在的位置(城市信息) 前几天做项目用到, 代码贴给大家. /// <summary> /// 获取当前位置的经纬度 ... 
- java去全半角空格,trim(), replaceAll(" +",""),replaceAll("\\s*", ""), replaceAll(" | ", "")
			JAVA中去掉空格 . String.trim() trim()是去掉首尾空格 .str.replace(" ", ""); 去掉所有空格,包括首尾.中间 St ... 
- 此文本文件包含的数据无法放置在一个工作表中 gb2312
			excel导入csv,csv要从unicode转为gb2312, 否则提示:此文本文件包含的数据无法放置在一个工作表中 
- 聊聊高并发(二十九)解析java.util.concurrent各个组件(十一) 再看看ReentrantReadWriteLock可重入读-写锁
			上一篇聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁 讲了可重入读写锁的基本情况和基本的方法,显示了怎样 ... 
- ZOJ 3822 Domination(概率dp 牡丹江现场赛)
			题目链接:problemId=5376">http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5376 Edward ... 
- 阐述php(四) 流量控制
			一个.选择结构 1. 单路分支 <? php if(条件){ 运行一条语句; } ?> 2. 双路分支 <?php if(条件) 运行一条语句; }else 运行一条语句; } ?& ... 
