状态模式
这两个模式UML相同,都是多态的应用,其实他们的运用场景有很大区别。
1、策略模式
封装算法,让使用者可以更换不同的算法。变is a为has a 用组合来代替继承。
一旦置入算法,不会因使用者的内部状态来改变算法。
采用哪种算法,是由使用者掌握的。
2、状态模式
对象的内部状态决定它的行为。不同的状态有不同的行为,不同的行为又切换不同的状态。
当方法内出现很多if else时可以考虑使用状态模式。
状态模式重要的一点是在行为执行时,状态的变更。
策略模式的孪生兄弟---状态模式
如果我们在编写代码的时候,遇到大量的条件判断的时候,可能会采用策略模式来优化结构,因为这时涉及到策略的选择,但有时候仔细查看下,就会发现,这些所谓的策略其实是对象的不同状态,更加明显的是,对象的某种状态也成为判断的条件。
使用场景
考虑一个在线投票系统的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所投的票;如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。
要使用状态模式实现,首先需要把投票过程的各种状态定义出来,根据以上描述大致分为四种状态:正常投票、反复投票、恶意刷票、进入黑名单。然后创建一个投票管理对象(相当于Context)。
public interface VoteState { /** * 处理状态对应的行为 * @param user 投票人姓名 * @param voteItem 投票项(赞成,反对,弃权) * @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候, * 可以回调上下文的数据 */ public void vote(String user,String voteItem,VoteManager voteManager); }
具体状态类——正常投票
public class NormalVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { //正常投票,记录到投票记录中 voteManager.getMapVote().put(user, voteItem); System.out.println("恭喜投票成功"); } }
具体状态类——重复投票
public class RepeatVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { //重复投票,暂时不做处理 System.out.println("请不要重复投票"); } }
具体状态类——恶意刷票
public class SpiteVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { // 恶意投票,取消用户的投票资格,并取消投票记录 String str = voteManager.getMapVote().get(user); if(str != null){ voteManager.getMapVote().remove(user); } System.out.println("你有恶意刷屏行为,取消投票资格"); } }
具体状态类——黑名单
public class BlackVoteState implements VoteState { @Override 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 */ 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 += 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<9;i++){ vm.vote("周永康","赞成"); } } }
运行结果如下:
从上面的示例可以看出,状态的转换基本上都是内部行为,主要在状态模式内部来维护。比如对于投票的人员,任何时候他的操作都是投票,但是投票管理对象的处理却不一定一样,会根据投票的次数来判断状态,然后根据状态去选择不同的处理。
(adsbygoogle = window.adsbygoogle || []).push({});
- 状态模式
- State状态设计模式
- 设计模式入门-状态模式(php版)
- 状态(State)模式--------用类表示状态
- android设计模式之---状态模式
- 24天学会设计模式------状态模式
- 设计模式——状态模式(State)
- 设计模式学习笔记-状态模式
- Java开发中的23种设计模式详解----状态模式(State)
- 设计模式之状态模式
- 处理对象的多种状态及其相互转换——状态模式(State Pattern)
- IOS第13天(3,私人通讯录,登陆状态数据存储,数据缓存, cell的滑动删除,进入编辑模式,单个位置刷新 )
- 状态模式教你学会清蒸鲤鱼
- 行为型模式之状态模式(State)
- 设计模式与泡mm的关系之state状态模式及再思考
- 生活中的状态模式
- JAVA开发的23种设计模式之 --- 状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之十二:状态模式(State)