设计模式之状态模式

状态决定行为。由于状态在运行期间是可以被改变的。在VoteManager类中根据条件来创建不同的状态实现类,于是到最后就会调用不同的逻辑。
看起来同一个对象,在不同的运行时刻,行为是不一样的,就像是类被修改了一样!

场景:投票,根据票数不同,给用户不用反馈

  1. 无模式情况

设计模式之状态模式_第1张图片

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");
        }
    }
}

  1. 标准模式
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) {

    }
}

执行效果

设计模式之状态模式_第2张图片

  1. 应用模式
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");
        }
    }
}

总结

状态模式的调用顺序
设计模式之状态模式_第3张图片
状态模式的应用:
工作流,根据不同条件判断,执行不同的业务
状态模式的优点:

设计模式之状态模式_第4张图片

设计模式之状态模式_第5张图片鱼与熊掌本就不可兼得。有时候业务就是比较复杂。引入合理的设计有助理提高代码的可扩展性。提高了代码的复杂程度在所难免。

什么时候选择使用状态模式?

设计模式之状态模式_第6张图片

设计模式之状态模式_第7张图片

以上内容参考《研磨设计模式》

你可能感兴趣的:(设计模式,状态模式,java)