设计模式—状态模式

作者: HJXANDHMR | 来源:发表于2016-06-12 18:31 被阅读2912次

今天我们来学习一种行为型模式,状态模式(State Pattern)。

模式定义

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States)。

模式结构

状态模式包含如下角色:

**Context: ** 环境类
**State: ** 抽象状态类
**ConcreteState: **具体状态类

UML图

代码实现

大家都知道水是有几种状态的,我们就来模拟水状态的转变。

IWaterState.java

/**
 * 抽象状态类
 */
public interface IWaterState {

    void printState();
}

IceWaterState.java

/**
 * 冰水
 */
public class IceWaterState implements IWaterState {

    @Override
    public void printState() {
        System.out.println("Now state: Ice Water");
    }
}

WarmWaterState.java

/**
 * 温水
 */
public class WarmWaterState implements IWaterState {
    @Override
    public void printState() {
        System.out.println("Now state: Warm Water");
    }
}

BoilingWaterState.java

/**
 * 沸水
 */
public class BoilingWaterState implements IWaterState {
    @Override
    public void printState() {
        System.out.println("Now state: Boiling Water");
    }
}

WaterContext.java


/**
 * 环境类
 */
public class WaterContext {
    private IWaterState mIWaterState;

    public IWaterState getIWaterState() {
        return mIWaterState;
    }

    public void setIWaterState(int i) {
        if (i == 0) {
            mIWaterState = new IceWaterState();
            return;
        }

        if (i == 1) {
            mIWaterState = new WarmWaterState();
            return;
        }

        if (i == 2) {
            mIWaterState = new BoilingWaterState();
            return;
        }
    }
}

测试类


 public class MyClass {

    public static void main(String[] args) {
        IWaterState iWaterState;
        WaterContext waterContext = new WaterContext();
        //模拟状态改变
        for (int i = 0; i < 3; i++) {
            waterContext.setIWaterState(i);
            iWaterState = waterContext.getIWaterState();
            System.out.println("i=" + i);
            iWaterState.printState();
        }
    }
}

运行结果

模式分析

  • 状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。
  • 状态模式的关键是引入了一个抽象类来专门表示对象的状态,这个类我们叫做抽象状态类,而对象的每一种具体状态类都继承了该类,并在不同具体状态类中实现了不同状态的行为,包括各种状态之间的转换。

在状态模式结构中需要理解环境类与抽象状态类的作用:

  • 环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作。

  • 抽象状态类可以是抽象类,也可以是接口,不同状态类就是继承这个父类的不同子类,状态类的产生是由于环境类存在多个状态,同时还满足两个条件: 这些状态经常需要切换,在不同的状态下对象的行为不同。因此可以将不同对象下的行为单独提取出来封装在具体的状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,对象看起来似乎修改了它的类,而实际上是由于切换到不同的具体状态类实现的。由于环境类可以设置为任一具体状态类,因此它针对抽象状态类进行编程,在程序运行时可以将任一具体状态类的对象设置到环境类中,从而使得环境类可以改变内部状态,并且改变行为。

状态模式的优点

  • 封装了转换规则。

  • 枚举可能的状态,在枚举状态之前需要确定状态种类。

  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

状态模式的缺点

  • 状态模式的使用必然会增加系统类和对象的个数。

  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

  • 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

本博客同步发表在http://hjxandhmr.github.io/2016/06/12/DesignPattern-State/

参考
http://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/state.html

相关文章

  • 设计模式-状态模式

    设计模式-状态模式 设计模式 状态模式的关键是区分事物内部的状态

  • 设计模式——状态模式

    设计模式——状态模式 在状态模式中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。 优点: 减少...

  • 设计模式-状态设计模式

    1.定义 对于某个操作,由于其状态的不同,表现出的行为会不同(如遥控器进行音量增加的操作,在电视是开机状态下是可以...

  • 设计模式——状态模式

    前言 设计模式是指导一个程序猿以更好的姿态处理一些问题,而不再像刚学编程的我们,只会使用if-else分支语句,或...

  • 设计模式--状态模式

    基本常识:策略模式与状态模式是双胞胎,在出生时才分开。 假设公司有个糖果机,1当糖果机由糖果,投入25分钱,转动曲...

  • 设计模式——状态模式

    在阎宏博士的《JAVA与模式》一书中开头是这样描述状态(State)模式的:状态模式,又称状态对象模式(Patte...

  • 设计模式《状态模式》

    引言   上一节我们说了策略模式。这一节我们讲讲策略模式的双胞胎弟弟:状态模式,这个模式大家可能不常见,也不常用,...

  • 设计模式——状态模式

    定义 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行...

  • 设计模式 - 状态模式

    模式定义 允许一个对象在其内部状态发生改变时改变它的行为。对象看起来似乎修改了它的类。 状态模式(State Pa...

  • 设计模式 ——— 状态模式

    STATE(状态) ———— 对象行为型模式 意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改...

网友评论

  • 星耀之梦:上文说的对,楼主你这根本就不是状态模式。
    状态模式重点是 将状态的切换 封装在状态内部。
    应该在IcewaterState调用Context类的setState(State)。例如:
    锅炉加热H2O, H2O从固体-》液体-》气体

    Boiler{
    H20State state;
    setH20State(H20State state){
    this.state = state;
    }
    riseTemperature{
    state.riseTemperature();
    }
    }


    H20State{
    riseTemperature(Context)
    }

    H20StateSolid implements H20State {
    riseTemperature(Boiler boiler) {
    boiler.setState(new H20StateLiquid);
    }
    }

    H20StateLiquid implements H20State {
    riseTemperature(Boiler boiler) {
    boiler.setState(new H20StateGas);
    }
    }

    H20StateGas implements H20State {
    riseTemperature(Boiler boiler) {
    //State no change
    }
    }
  • 有心人问道:太感谢了!我第一次学习设计模式,这种模式我在我现在正在写的代码中无意间用到过,感觉就是不是特别好用。我想在软件中支持多种文件型数据库,就设计了楼主发表的状态模式的代码,因为那个软件要实现操作数据库方面的功能比较多,每个数据库都要实现一遍操作,太麻烦了。我觉得我应该在学学其他设计模式,看能不能找到更好的办法,还有可能我对数据库没理解透的原因。
    葉華千羽:@取次花丛 错在用 Magic Number 来定义状态,如果把 setIWaterState() 的参数改为 IWaterState 接口类型就没有判断了
    11be8d90b031:这是状态模式?状态转换在哪儿?所有的判断逻辑又出现在环境类中了
    HJXANDHMR:@YxrWendao 共同进步 :blush:

本文标题:设计模式—状态模式

本文链接:https://www.haomeiwen.com/subject/juoedttx.html