• 设计模式--状态模式


    状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

    State类,抽象状态类,定义一个接口以封装与Context的一个特定的状态相关的行为

    1 public abstract class State {
    2     public abstract void handle(Context context);
    3 }

    ConcreteStat类,具体的状态类,每一个子类实现一个与Context的一个状态相关的行为

    public class ConcreteStateA extends State {
    
        @Override
        public void handle(Context context) {
            context.state = new ConcreteStateB();
        }
    
    }
    
    
    public class ConcreteStateB extends State {
    
        @Override
        public void handle(Context context) {
            context.state = new ConcreteStateA();
        }
    
    }

    Context类,维护一个concreteState子类的实例,这个实例定义当前的状态。

     1 public class Context {
     2 
     3     public State state;
     4 
     5     public Context(State state) {// 定义Context的初始状态
     6         this.state = state;
     7     }
     8 
     9     public State getState() {
    10         return state;
    11     }
    12 
    13     public void setState(State state) {
    14         this.state = state;
    15     }
    16 
    17     public void requiest() {
    18         state.handle(this);// 对请求做处理,并设置下一状态
    19         System.out.println(state.getClass().getName());
    20     }
    21 }

    测试

     1 public class StateDemo {
     2     public static void main(String[] args) {
     3         Context c = new Context(new ConcreteStateA());//设置context的初始状态为C...A
     4         c.requiest();
     5         c.requiest();
     6         c.requiest();
     7         c.requiest();
     8         
     9     }
    10 }

    使用场景(转载自 http://www.cnblogs.com/java-my-life/archive/2012/06/08/2538146.html)

      考虑一个在线投票系统的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过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("u1","A");
            }
        }
    
    }
    复制代码

      运行结果如下:

      从上面的示例可以看出,状态的转换基本上都是内部行为,主要在状态模式内部来维护。比如对于投票的人员,任何时候他的操作都是投票,但是投票管理对象的处理却不一定一样,会根据投票的次数来判断状态,然后根据状态去选择不同的处理。

  • 相关阅读:
    win10安装vue
    通过docker安装rabbitmq
    python定时访问主机进程信息并反馈到远程服务器
    win10配置Apache+部署静态html页面
    HTTP协议—HTTP报文格式详解
    python脚本编写(纯干货)
    linux/CentOS的安装(萌新版)
    gradle中调用ant.unzip对zip包解压缩
    通过gradle运行测试脚本
    使用rest-assured测试rest service, 遇到“415 Unsupported Media Type”
  • 原文地址:https://www.cnblogs.com/sun-space/p/5778232.html
Copyright © 2020-2023  润新知