资讯专栏INFORMATION COLUMN

设计模式-状态模式

williamwen1986 / 949人阅读

摘要:定义状态模式,当一个对象的内部状态改变时允许改变其行为,这个对象看起来像是改变了其类。总结状态模式和和策略模式有点相像,状态模式的状态转移是内部控制的,而策略模式是由客户端控制采用不同的策略。

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

Context:环境,上下文,其实就是状态管理者,隐藏了状态之间转换的细节,是客户端与各个状态的中间人。request()方法是客户端调用的,

State:抽象状态,定义了状态的处理抽象方法handle(),各个具体状态需要实现它。

ConcreteState:具体状态,实现了状态的公共方法,且包含了状态转换的判断。

经典源码

状态管理者

public class Context {
    //持有一个State类型的对象实例
    private State state;

    public void setState(State state) {
        this.state = state;
    }
    /**
     * 客户端调用
     */
    public void request(String sampleParameter) {
        //转调state来处理
        state.handle(sampleParameter);
    }
}

抽象状态

public interface State {
    /**
     * 状态对应的处理
     */
    public void handle(String sampleParameter);
}

具体状态A

public class ConcreteStateA implements State {

    @Override
    public void handle(String sampleParameter) {
        
        System.out.println("ConcreteStateA handle :" + sampleParameter);
    }

}

具体状态B

public class ConcreteStateB implements State {

    @Override
    public void handle(String sampleParameter) {
        
        System.out.println("ConcreteStateB handle :" + sampleParameter);
    }

}
客户端调用方
public class Client {

    public static void main(String[] args){
        //创建状态
        State state = new ConcreteStateB();
        //创建环境
        Context context = new Context();
        //将状态设置到环境中
        context.setState(state);
        //请求
        context.request("test");
    }
}
实际案例 背景

小A正在召唤师峡谷厮杀,他玩的是卡特,买了一本杀人书。随着游戏时间的进行,小A杀的人越来越多,且自己都没死过,游戏中不断传来“XXX暴走了”、“XXX主宰了比赛”、“XXX接近神了”。最终小A以12杀0死的完美战绩结束了比赛,脑海中刚才的捷报声还在不停环绕在他的耳边,他就想这不就是状态模式,随后打开IDE开始复现刚才的过程。

结构

环境类

package com.jo.state;

/**
 * @author Jo
 * @date 2018/1/17
 */
public class LolContext {
    /**
     * 当前杀人状态
     */
    private KillState killState;

    /**
     * 当前杀人数
     */
    private Integer killNum = 0;

    public LolContext() {
        killState = new Normal();
    }

    public Integer getKillNum() {
        return killNum;
    }

    public LolContext setKillState(KillState killState) {
        this.killState = killState;
        return this;
    }

    /**
     * 杀人方法,
     */
    public void kill(){
        killNum += 1;
        killState.kill(this);
        System.out.println("当前击杀数" + killNum);
        System.out.println();
    }
}

抽象杀人状态

public interface KillState {
    /**
     * 抽象杀人方法
     * @param lolContext
     */
    void kill(LolContext lolContext);
}

普通击杀

public class Normal implements KillState {
    @Override
    public void kill(LolContext lolContext) {
        System.out.println("你杀了一个人");
        //杀了2个人的时候转换状态
        if (lolContext.getKillNum() > 1){
            lolContext.setKillState(new KillingSpring());
        }
    }
}

大杀特杀

public class KillingSpring implements KillState {
    @Override
    public void kill(LolContext lolContext) {
        System.out.println("你正在大杀特杀");
        lolContext.setKillState(new Rampage());
    }
}

接近暴走

public class Rampage implements KillState {
    @Override
    public void kill(LolContext lolContext) {
        System.out.println("你已经接近暴走了");
        lolContext.setKillState(new Unstoppable());
    }
}

无人可挡

public class Unstoppable implements KillState {
    @Override
    public void kill(LolContext lolContext) {
        System.out.println("你已经无人可挡了");
        lolContext.setKillState(new Dominating());
    }
}





超神

public class Legendary implements KillState {
    @Override
    public void kill(LolContext lolContext) {
        System.out.println("你已经超神了");
    }
}

客户端调用

public class Client {
    public static void main(String[] args) {
        LolContext lolContext = new LolContext();
        for (int i = 0; i < 13; i++) {
            lolContext.kill();
        }
    }
}

运行结果

客户端只负责调用LolContext的kill方法,其余一概不知,内部便会随着杀人数的增长打印不同的通知。而LolContext中也没有复杂,一大串的if else switch case,状态的转移在各自的具体状态中,如果需要修改部分逻辑只需要改对应的状态,而不需要改原本在一起的if else,大大减少了隐患的发生率,从而不会发生牵一发而动全身的结果。

适用场景

状态模式的优点是解除了程序的耦合度,采用子类的方式去除了烦琐容易出错的if else,但反而带来的是类的数据增多。如果你要实现的功能状态不多,且功能简单,那不推荐使用状态模式,不然会徒增程序的复杂性。且要执行的动作有一定的复杂度,此例的kill方法是最简单的实现,实际应用中复杂度是远远大于它的。你可以想象在状态多,且复杂的动作中不使用状态模式会事怎样,if else多的眼花缭乱,上一个if和下一个else if相差几百行代码,想必这样的代码谁都不愿意碰,万一改坏了就要背锅了。

总结

状态模式和和策略模式有点相像,状态模式的状态转移是内部控制的,而策略模式是由客户端控制采用不同的策略。因此在目的和实现还是有很大的差别的。有些场景“状态”不是那么明显,需要转换成状态模式就考察使用者的功底和对业务的理解程度了,望大家都能get更多知识点,能力越来越强,个个都是架构师。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68263.html

相关文章

  • JS 状态模式

    摘要:简介状态模式允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类。状态通常为一个或多个枚举常量的表示。简而言之,当遇到很多同级或者的时候,可以使用状态模式来进行简化。 1. 简介 状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类。其实就是用一个对象或者数组记录一组状态,每个状态对应一个实现,实现的时候根据状态挨个去运...

    xingqiba 评论0 收藏0
  • 状态模式

    摘要:在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的对象。缺点状态模式的使用必然会增加系统类和对象的个数。状态模式是指允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,我们创建表示各种状态的对象和一个行为随着状...

    Eric 评论0 收藏0
  • 一起学设计模式 - 备忘录模式

    摘要:备忘录模式常常与命令模式和迭代子模式一同使用。自述历史所谓自述历史模式实际上就是备忘录模式的一个变种。在备忘录模式中,发起人角色负责人角色和备忘录角色都是独立的角色。 备忘录模式(Memento Pattern)属于行为型模式的一种,在不破坏封装特性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。 概述 备忘录模式又叫做快照模式(...

    roland_reed 评论0 收藏0
  • 设计模式状态模式

    摘要:为了实现这个正义偷笑又合理的诉求,你得先学会今天要介绍的设计模式,因为你们公司的这个流程可能就是用今天这个模式设计的。状态模式对开闭原则的支持并不太好,新增状态时,不仅得增加状态类,还得修改原来已经有的状态,让之前的状态切换到新增的状态。一、定义你是否经常请(偷)假(懒)?是不是对公司万恶的请假申请流程深恶痛绝。有没有想过偷偷改造这个万恶的系统,从 申请->项目经理审批->部门审批->老板审...

    zhangke3016 评论0 收藏0
  • FSM状态机之状态模式

    摘要:要注意这里的一个状态行为因为这个词是状态模式中最重要的个概念。考虑到这点,聪明的在中推出了状态机这个伪函数,能够帮助我们快速实现状态化。这里就引入了状态机这个概念,以及和他对应的状态表。  首先声明一点,这个模式是我目前见过最好用(本人观点),但是也是最难理解的一个(本人观点)。 所以大家需要做好心理准备,如果,对这个模式没有特别强烈的需求,比如: 我有一个Button,我按次数点击它...

    k00baa 评论0 收藏0

发表评论

0条评论

williamwen1986

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<