状态决定行为。由于状态在运行期间是可以被改变的。在VoteManager类中根据条件来创建不同的状态实现类,于是到最后就会调用不同的逻辑。
看起来同一个对象,在不同的运行时刻,行为是不一样的,就像是类被修改了一样!
场景:投票,根据票数不同,给用户不用反馈
- 无模式情况
package com.tao.YanMoDesignPattern.status.notPattern;import java.util.HashMap;
import java.util.Map;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 投票管理* @Version 1.0**/public class VoteManager {// 记录用户投票的结果 用户名称,投票的选择private Map<String,String> mapVote = new HashMap<String,String>();// 记录用户投票的次数 用户名称,投票的次数private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();public Map<String, String> getMapVote() {return mapVote;}public Map<String, Integer> getMapVoteCount() {return mapVoteCount;}/*** 投票** @param user 用户* @param voteItem 投票项*/public void vote(String user,String voteItem){//1、 先为该用户增加投票的次数// 从记录中取出已有的投票次数Integer oldVotCount = mapVoteCount.get(user);if (oldVotCount == null){oldVotCount = 0;}oldVotCount += 1;mapVoteCount.put(user,oldVotCount);// 2、判断该用户的类型,到底是正常投票,重复投票还是恶意投票// 还是上黑名单,然后根据投票类型来进行 相应的操作if (oldVotCount == 1){// 正常投票,记录到投票记录中mapVote.put(user,voteItem);System.out.println("恭喜你投票成功!");}else if (oldVotCount > 1 && oldVotCount < 5){// 重复投票,暂不做处理System.out.println("请不要重复投票");}else if (oldVotCount > 5 && oldVotCount < 8){//恶意投票 取消用户的投票资格,并取消投票记录String s = mapVote.get(user);if (s != null){mapVote.remove(user);}System.out.println("你有恶意刷票行为,取消投票资格!");} else if (oldVotCount > 8) {// 黑名单System.out.println("进入黑名单,将禁止登陆和适用本系统");}}
}
测试类
package com.tao.YanMoDesignPattern.status.notPattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 客户端测试* @Version 1.0**/
public class Client {public static void main(String[] args) {VoteManager vm = new VoteManager();for (int i=0;i<8;i++){vm.vote("u1","A");}}
}
- 标准模式
package com.tao.YanMoDesignPattern.status.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 封装与 Context 的一个特定状态相关的行为* @Version 1.0**/
public interface State {/*** 处理对应的状态** @param sampleParameter 样本参数*/public void Handle(String sampleParameter);
}
package com.tao.YanMoDesignPattern.status.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class Context {/*** 持有一个State 类型的对象实例*/private State state;/*** 设置实现State 的对象实例* @param state*/public void setState(State state) {this.state = state;}/*** 用户感兴趣的接口方法* @param sampleParameter 样本参数*/public void request(String sampleParameter){//在处理中,会转调state 来处理state.Handle(sampleParameter);}
}
package com.tao.YanMoDesignPattern.status.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 实现一个与context 的一个特定状态相关的行为* @Version 1.0**/
public class ConcreteStateA implements State{@Overridepublic void Handle(String sampleParameter) {}
}
package com.tao.YanMoDesignPattern.status.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 实现一个与context 的一个特定状态相关的行为* @Version 1.0**/
public class ConcreteStateB implements State{@Overridepublic void Handle(String sampleParameter) {}
}
执行效果
- 应用模式
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 封装一个投票状态相关的行为* @Version 1.0**/
public interface VoteState {/*** 投票** @param user 用户* @param voteItem 投票项* @param voteManager 投票上线文,用来在实现状态相应的功能出来的时候,可以回调上下文的数据*/public void vote(String user, String voteItem, VoteManager voteManager);
}
投票类型,也就是不同的状态
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class SpiteVoteState implements VoteState{@Overridepublic void vote(String user, String voteItem, VoteManager voteManager) {//恶意投票,取消用户投票资格,并取消投票记录String s = voteManager.getMapVote().get(user);if (s!=null){voteManager.getMapVote().remove(user);}System.out.println("你有恶意刷票行为,取消投票资格!");}
}
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class RepeatVoteState implements VoteState{@Overridepublic void vote(String user, String voteItem, VoteManager voteManager) {//重复投票,暂不做处理System.out.println("请不要重复投票!");}
}
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class NormalVoteState implements VoteState{@Overridepublic void vote(String user, String voteItem, VoteManager voteManager) {//z正常投票 , 记录到投票记录中voteManager.getMapVote().put(user,voteItem);System.out.println("恭喜你投票成功!");}
}
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class BlackVoteState implements VoteState{@Overridepublic void vote(String user, String voteItem, VoteManager voteManager) {//黑名单,禁止登陆系统System.out.println("进入黑名单,将禁止登陆和适用本系统");}
}
应用状态模式的核心类
package com.tao.YanMoDesignPattern.status.caseChange;import java.util.HashMap;
import java.util.Map;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 投票管理* @Version 1.0**/
public class VoteManager {// 持有状态处理的对象private VoteState state = null;// 记录用户投票的结果 用户名称,投票的选项private Map<String, String> mapVote = new HashMap<String, String>();// 记录用户投票的次数 用户名称,投票的次数private Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();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;// TODO 下面这个代码如果没有的话,无法记录用户是否已经投过票。相当重要mapVoteCount.put(user,oldVoteCount);//判断用户的类型,就相当于是判断对应的状态// 到底是正常投票,重复投票,恶意投票还是上黑名单的状态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);}
}
测试类
package com.tao.YanMoDesignPattern.status.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 客户端测试* @Version 1.0**/
public class Client {public static void main(String[] args) {VoteManager vm = new VoteManager();for (int i=0;i<8;i++){vm.vote("u1","A");}}
}
总结
状态模式的调用顺序
状态模式的应用:
工作流,根据不同条件判断,执行不同的业务
状态模式的优点:
鱼与熊掌本就不可兼得。有时候业务就是比较复杂。引入合理的设计有助理提高代码的可扩展性。提高了代码的复杂程度在所难免。
什么时候选择使用状态模式?
以上内容参考《研磨设计模式》