状态模式(State)
2016-07-23 12:39
351 查看
1. 模式的定义
考虑一个在线投票的应用。状态模式的定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
2. UML图
Context:上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象
State:状态接口,用来封装与上下文的一个特定状态所对应的行为
ConcreteState:具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理
代码:
/** * 封装一个投票状态相关的行为 */ public interface VoteState { /** * 处理状态对应的行为 * @param user 投票人 * @param voteItem 投票项 * @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候, * 可以回调上下文的数据 */ public void vote(String user,String voteItem,VoteManager voteManager); } public class NormalVoteState implements VoteState{ public void vote(String user, String voteItem, VoteManager voteManager) { //正常投票 //记录到投票记录中 voteManager.getMapVote().put(user, voteItem); System.out.println("恭喜你投票成功"); } } public class RepeatVoteState implements VoteState{ public void vote(String user, String voteItem, VoteManager voteManager) { //重复投票 //暂时不做处理 System.out.println("请不要重复投票"); } } public class SpiteVoteState implements VoteState{ public void vote(String user, String voteItem, VoteManager voteManager) { //恶意投票 //取消用户的投票资格,并取消投票记录 String s = voteManager.getMapVote().get(user); if(s!=null){ voteManager.getMapVote().remove(user); } System.out.println("你有恶意刷票行为,取消投票资格"); } } public class BlackVoteState implements VoteState{ public void vote(String user, String voteItem, VoteManager voteManager) { //黑名单 //记入黑名单中,禁止登录系统了 System.out.println("进入黑名单,将禁止登录和使用本系统"); } } /** * 投票管理 */ public class VoteManager { /** * 持有状态处理对象 */ private VoteState state = null; /** * 记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项> */ private Map<String,String> mapVote = new HashMap<String,String>(); /** * 记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数> */ private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>(); /** * 获取记录用户投票结果的Map * @return 记录用户投票结果的Map */ public Map<String, String> getMapVote() { return mapVote; } /** * 投票 * @param user 投票人,为了简单,就是用户名称 * @param voteItem 投票的选项 */ public void vote(String user,String voteItem){ //1:先为该用户增加投票的次数 //先从记录中取出已有的投票次数 Integer oldVoteCount = mapVoteCount.get(user); if(oldVoteCount==null){ oldVoteCount = 0; } oldVoteCount = oldVoteCount + 1; mapVoteCount.put(user, oldVoteCount); //2:判断该用户投票的类型,就相当于是判断对应的状态 //到底是正常投票、重复投票、恶意投票还是上黑名单的状态 if(oldVoteCount==1){ state = new NormalVoteState(); }else if(oldVoteCount>1 && oldVoteCount<5){ state = new RepeatVoteState(); }else if(oldVoteCount >= 5 && oldVoteCount<8){ state = new SpiteVoteState(); }else if(oldVoteCount>=8){ state = new BlackVoteState(); } //然后转调状态对象来进行相应的操作 state.vote(user, voteItem, this); } } public class Client { public static void main(String[] args) { VoteManager vm = new VoteManager(); for(int i=0;i<8;i++){ vm.vote("u1", "A"); } } }
3. 研磨设计模式
1)不同的状态对应的状态处理(行为)是不相同的2)状态模式的行为是平行性的(层次一样,相互独立,没有关联),不可相互替换,而策略模式的行为是平等性的,是可以相互替换的
3)状态模式的本质:根据状态来分离和选择行为
4)工作流
请假的工作流:
/** * 公共状态处理机,相当于状态模式的Context * 包含所有流程使用状态模式时的公共功能 */ public class StateMachine { /** * 持有一个状态对象 */ private State state = null; /** * 包含流程处理需要的业务数据对象,不知道具体类型, * 用Object,反正只是传递到具体的状态对象里面 */ private Object businessVO = null; /** * 执行工作,客户端处理流程的接口方法。 * 在客户完成自己的业务工作后调用 */ public void doWork(){ //转调相应的状态对象真正完成功能处理 this.state.doWork(this); } public State getState() { return state; } public void setState(State state) { this.state = state; } public Object getBusinessVO() { return businessVO; } public void setBusinessVO(Object businessVO) { this.businessVO = businessVO; } } /** * 公共状态接口 */ public interface State { /** * 执行状态对应的功能处理 * @param ctx 上下文的实例对象 */ public void doWork(StateMachine ctx); } /** * 请假单对象 */ public class LeaveRequestModel { /** * 请假人 */ private String user; /** * 请假开始时间 */ private String beginDate; /** * 请假天数 */ private int leaveDays; /** * 审核结果 */ private String result; public String getResult() { return result; } public void setResult(String result) { this.result = result; } public String getUser() { return user; } public String getBeginDate() { return beginDate; } public int getLeaveDays() { return leaveDays; } public void setUser(String user) { this.user = user; } public void setBeginDate(String beginDate) { this.beginDate = beginDate; } public void setLeaveDays(int leaveDays) { this.leaveDays = leaveDays; } } public class LeaveRequestContext extends StateMachine{ //这里可以扩展跟自己流程相关的处理 } public interface LeaveRequestState extends State{ //这里可以扩展跟自己流程相关的处理 } /** * 处理项目经理的审核,处理后可能对应部门经理审核、审核结束之中的一种 */ public class ProjectManagerState implements LeaveRequestState{ public void doWork(StateMachine request) { //先把业务对象造型回来 LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO(); System.out.println("项目经理审核中,请稍候......"); //模拟用户处理界面,通过控制台来读取数据 System.out.println(lrm.getUser()+"申请从"+lrm.getBeginDate()+ "开始请假"+lrm.getLeaveDays()+"天,请项目经理审核(1为同意,2为不同意):"); //读取从控制台输入的数据 Scanner scanner = new Scanner(System.in); if(scanner.hasNext()){ int a = scanner.nextInt(); //设置回到上下文中 String result = "不同意"; if(a==1){ result = "同意"; } lrm.setResult("项目经理审核结果:"+result); //根据选择的结果和条件来设置下一步 if(a==1){ if(lrm.getLeaveDays() > 3){ //如果请假天数大于3天,而且项目经理同意了,就提交给部门经理 request.setState(new DepManagerState()); //继续执行下一步工作 request.doWork(); }else{ //3天以内的请假,由项目经理做主,就不用提交给部门经理了,转向审核结束状态 request.setState(new AuditOverState()); //继续执行下一步工作 request.doWork(); } }else{ //项目经理要是不同意的话,也就不用提交给部门经理了,转向审核结束状态 request.setState(new AuditOverState()); //继续执行下一步工作 request.doWork(); } } } } /** * 处理部门经理的审核,处理后对应审核结束状态 */ public class DepManagerState implements LeaveRequestState{ public void doWork(StateMachine request) { //先把业务对象造型回来 LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO(); System.out.println("部门经理审核中,请稍候......"); //模拟用户处理界面,通过控制台来读取数据 System.out.println(lrm.getUser()+"申请从"+lrm.getBeginDate()+ "开始请假"+lrm.getLeaveDays()+"天,请部门经理审核(1为同意,2为不同意):"); //读取从控制台输入的数据 Scanner scanner = new Scanner(System.in); if(scanner.hasNext()){ int a = scanner.nextInt(); //设置回到上下文中 String result = "不同意"; if(a==1){ result = "同意"; } lrm.setResult("部门经理审核结果:"+result); //部门经理审核过后,直接转向审核结束状态了 request.setState(new AuditOverState()); //继续执行下一步工作 request.doWork(); } } } /** * 处理审核结束的类 */ public class AuditOverState implements LeaveRequestState{ public void doWork(StateMachine request) { //先把业务对象造型回来 LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO(); System.out.println(lrm.getUser()+",你的请假申请已经审核结束,结果是:"+lrm.getResult()); } } public class Client { public static void main(String[] args) { //创建业务对象,并设置业务数据 LeaveRequestModel lrm = new LeaveRequestModel(); lrm.setUser("小李"); lrm.setBeginDate("2010-02-08"); lrm.setLeaveDays(5); //创建上下文对象 LeaveRequestContext request = new LeaveRequestContext(); //为上下文对象设置业务数据对象 request.setBusinessVO(lrm); //配置上下文,作为开始的状态,以后就不管了 request.setState(new ProjectManagerState()); //请求上下文,让上下文开始处理工作 request.doWork(); } }
相关文章推荐
- ios创建空项目
- vector::begin
- Openstack贡献者须知 2 — 社区工作运作 & 代码贡献流程
- 解决磁盘io紧张的一种临时方法
- 通道类型
- Git 一篇搞定基本操作
- 文件系统缓存dirty_ratio与dirty_background_ratio两个参数区别
- Redis教程分享系列:1.Redis基础入门
- ggplot2--legend图例的修改
- session与cookie的区别---
- Java泛型的实现:原理与问题
- 复杂度nlog(n)之归并排序
- 整数在内存中的表达
- 通过nfs挂载共享目录的方式搭建lamp平台并安装wordpress(一)
- kobject.c 添加注释
- 面试题29:数组中出现次数超过一半的数字
- 最小树形图
- 用Jplayer做的一个带动画的播放器
- 校外分散实习(13)
- 《架构探险》之数据访问层代码优化