状态模式---State

Posted 高高for 循环

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状态模式---State相关的知识,希望对你有一定的参考价值。

状态模式

根据状态决定行为


定义:

GOF《设计模式》中给状态模式下的定义为:允许一个对象在其内部状态改变时改变它的行为。

  • 能够让程序根据不同的外部情况来做出不同的响应,最直接的方法就是在程序中将这些 可能发生的外部情况全部考虑到,使用if else 语句来进行代码响应选择。但是这种方法对于复杂一点的状态判断,就会显得杂乱无章,容易产生错误,而且增加一个新的状态将会带来大量的修改。
  • 这个时候“根据状态决定行为”的状态模式的引入也许是个不错的主意。状态模式可以有效的替换充满在程序中的 if else 语句:将不同条件下的行为封装在一个类里面,再给这些类一个统一的父类来约束他们

组成:



生活中的状态模式:

  1. 以水为例,水之三态,固、液、气,三种状态表现出不同的特性和行为,它们之间的转换也伴随着热力学的现象。
  2. 电梯,有运行状态、开门状态、闭门状态、停止状态等
  3. QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作
  4. java线程分为:新建状态(New),就绪状态(Runnable),运行状态(Running),阻塞状态(Blocked),死亡状态(Dead)

案例1 :

需求:

  • 一个漂亮的MM 有开心和悲伤两种状态,且不同转态下,MM说的话,和哭笑的动作,都会根据状态的不同而不同.

普通 if else来判断:

MM:

public class MM {
    //姓名
    String name;
    //转态
    MMState state;

    //内置状态的类别,分为HAPPY,SAD2种
    private enum MMState {HAPPY, SAD}


    public void smile() {
        if(state.equals(MMState.HAPPY)){
            System.out.println("开怀大笑");
        }else if(state.equals(MMState.SAD)){
            System.out.println("无奈苦笑");
        }

    }

    public void cry() {
        if(state.equals(MMState.HAPPY)){
            System.out.println("喜极而泣");
        }else if(state.equals(MMState.SAD)){
            System.out.println("嚎啕大哭");
        }
    }

    public void say() {
        if(state.equals(MMState.HAPPY)){
            System.out.println("开心开心极了!!!");
        }else if(state.equals(MMState.SAD)){
            System.out.println("郁闷不说话!!!");
        }
    }

    public void setHappy(){
        this.state=MMState.HAPPY;
    }

    public void setSad(){
        this.state=MMState.SAD;
    }
}

测试:

public class Test01 {
    public static void main(String[] args) {
        MM mm = new MM();
        //设置转态为开心
        mm.setHappy();
        //调用方法
        mm.smile();
        mm.cry();
        mm.say();

        //改变状态为Sad
        mm.setSad();
        System.out.println("------------改变状态为Sad---------");

        //调用方法
        mm.smile();
        mm.cry();
        mm.say();

    }
}

状态模式实现:

抽象的转态角色:MMState

public abstract class MMState {
    abstract void smile();
    abstract void cry();
    abstract void say();
}

具体的开心转态角色: MMHappyState

public class MMHappyState extends MMState {
    @Override
    void smile() {
        System.out.println("开怀大笑");
    }

    @Override
    void cry() {
        System.out.println("喜极而泣");
    }

    @Override
    void say() {
        System.out.println("开心开心极了!!!");
    }
}

具体的悲伤转态角色: MMSadState

public class MMSadState extends MMState {
    @Override
    void smile() {
        System.out.println("无奈苦笑");
    }

    @Override
    void cry() {
        System.out.println("嚎啕大哭");
    }

    @Override
    void say() {
        System.out.println("郁闷不说话!!!");
    }
}

使用环境角色: MM

此时MM的行为方法,会根据状态state不同而自动改变

且MM增加状态时,代码结构也不需要再改变.

public class MM {
    //姓名
    String name;
    //状态 默认为开心状态
    MMState state = new MMHappyState();

    public void smile() {
        state.smile();
    }

    public void cry() {
        state.cry();
    }

    public void say() {
        state.say();
    }

}

测试

public class Test01 {
    public static void main(String[] args) {
        MM mm = new MM();
        //设置转态为开心
        mm.state=new MMHappyState();
        mm.smile();
        mm.cry();
        mm.say();

        //改变状态为Sad
        mm.state=new MMSadState();
        System.out.println("------------改变状态为Sad---------");

        //调用方法
        mm.smile();
        mm.cry();
        mm.say();

    }
}

有限转态机(FWM)


多线程–04–线程的生命周期

状态模式(State Pattern) 和有限转态机(State Machine)是2个东西,不要混淆在一起

总结

使用场景:

  • 对象的行为需要随着状态的改变而改变时。
  • 当我们一个操作中需要根据状态来写大量的if/else逻辑时

优点:

  1. 通过将每个状态设置为独立的对象,消除了代码中存在的大量if/else等判断分支,使得代码更加简洁,更容易维护。
  2. 将不同的状态通过不同的类来表示,使得状态切换时相比较于用数字或者字符串来表示时更加直观,转换目的也更加明确。
  3. 每个状态类的职责单一明确,易于扩展。

缺点:

  1. 状态过多会引起类膨胀(事实上这也是大部分设计模式的通病)。
  2. 状态模式的结构与实现相对较为复杂,容易造成代码混乱。
  3. 对于支持状态切换的状态类违反了开闭原则,因为一旦状态修改或者中间要新增状态,则需要修改对应的源代码,否则会出现状态切换错误。

注意事项:

  • 在行为受状态约束的情况下可以使用状态模式,使用时对象的状态最好不要超过5个

状态模式和策略模式对比:

状态模式和策略模式都能用来消除大量的if/else场景,但是也有本质区别。

  • 策略模式中各个策略之间是独立的,相互可以替换的,任意选择其中一个策略就能满足需求,而且是由客户端自己做出选择。而状态模式客户端只能选择初始节点,后续就会自动流转,各个状态是一个整体,不存在可以互相替换的状态。
  • 最根本的差异在于策略模式是在求解同一个问题的多种解法,这些不同解法之间毫无关联;状态模式则不同,状态模式要求各个状态之间有所关联,以便实现状态转移

区分这两个模式的关键是看行为是由状态驱动还是由一组算法驱动

以上是关于状态模式---State的主要内容,如果未能解决你的问题,请参考以下文章

State模式(状态设计模式)

设计模式之- 状态模式(State Pattern)

23种设计模式之状态模式(State)

尝试使用片段保存夜间模式状态

状态模式---State

程序设计模式 —— State 状态模式