状态决定行为。由于状态在运行期间是可以被改变的。在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{
@Override
public 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{
@Override
public 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{
@Override
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("你有恶意刷票行为,取消投票资格!");
}
}
package com.tao.YanMoDesignPattern.status.caseChange;
/**
* @Author Mi_Tao
* @Date 2023/7/22
* @Description
* @Version 1.0
**/
public class RepeatVoteState implements VoteState{
@Override
public 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{
@Override
public 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{
@Override
public 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");
}
}
}
状态模式的调用顺序
状态模式的应用:
工作流,根据不同条件判断,执行不同的业务
状态模式的优点:
鱼与熊掌本就不可兼得。有时候业务就是比较复杂。引入合理的设计有助理提高代码的可扩展性。提高了代码的复杂程度在所难免。
什么时候选择使用状态模式?
以上内容参考《研磨设计模式》