设计模式——状态模式

Posted 刘永祥

tags:

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

状态在我们的生活中是很常见的,比如我们交通使用的红绿信号灯,有红、黄、绿三种状态。其实我们的衣食住行都是状态,比如火车的启动,运行,暂停,状态几乎是无处不在。下面我们来看一个大家再熟悉不过的状态图

想必大家也都知道这几种状态的意义了。其实在我们程序里面状态也是很常见的,比如我们经常使用的switch语句就是最好的说明,case后面的值就是我们所说的状态值,线程的五种状态:新建状态、就绪状态、运行状态、阻塞状态、死亡状态。
言归正传!!!状态模式就是允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
状态模式的使用性:
1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 状态模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
状态模式的参与者:
环境类 : 定义一个接口。维护一个具体状态子类的实例,这个实例定义当前状态。
抽象状态类: 定义一个接口以封装与环境类的一个特定状态相关的行为。
具体状态类: 每一子类实现一个与环境类的一个状态相关的行为。
以购物里面的搜索商品,下订单、正在配送中、确认收货、订单评价这五个状态为例
抽象状态类ShoppingState.class

/**
 * 抽象状态类
 */
public interface ShoppingState 
    void handleState(Shopping shopping);
    String getState();

环境类Shopping.class

/**
 * 环境类
 */
public class Shopping 
    ShoppingState state;

    public void setState(ShoppingState state) 
        this.state = state;
    

    public void handle()
        state.handleState(this);
    

具体状态类SearchGoods.class

/**
 * 搜索商品的状态
 */
public class SearchGoods implements ShoppingState
    @Override
    public void handleState(Shopping shopping) 
        System.out.println(this.getState());
        ShoppingState state = new PlaceOrder();
        shopping.setState(state);
        state.handleState(shopping);
    
    @Override
    public String getState() 
        return "搜索商品已经完成!!!";
    

具体状态类PlaceOrder.class

/**
 * 下订单的状态
 */
public class PlaceOrder implements ShoppingState
    @Override
    public void handleState(Shopping shopping) 
        System.out.println(this.getState());
        ShoppingState state = new Distribution();
        shopping.setState(state);
        state.handleState(shopping);
    
    @Override
    public String getState() 
        return "下订单已经完成!!!";
    

具体状态类Distribution.class

/**
 * 商品配送的状态
 */
public class Distribution implements ShoppingState
    @Override
    public void handleState(Shopping shopping) 
        System.out.println(this.getState());
        ShoppingState state = new Receipt();
        shopping.setState(state);
        state.handleState(shopping);
    
    @Override
    public String getState() 
        return "商品配送已经完成!!!";
    

具体状态类Receipt.class

/**
 * 商品接收的状态
 */
public class Receipt implements ShoppingState
    @Override
    public void handleState(Shopping shopping) 
        System.out.println(this.getState());
        ShoppingState state = new Evaluate();
        shopping.setState(state);
        state.handleState(shopping);
    
    @Override
    public String getState() 
        return "商品接收已经完成!!!";
    

具体状态类Evaluate.class

/**
 * 评价的状态
 */
public class Evaluate implements ShoppingState
    @Override
    public void handleState(Shopping shopping) 
        System.out.println(this.getState());
        System.out.println("~~~~~~~~到此已经走完整个流程了~~~~~~~~");
    
    @Override
    public String getState() 
        return "评价已经完成!!!";
    

测试代码

Shopping shopping = new Shopping();
shopping.setState(new SearchGoods());
shopping.handle();

运行效果图

通过上面的代码我们可以很明显的看出状态模式的优缺点
优点:
封装了转换规则。
将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
状态模式的使用必然会增加系统类和对象的个数。
状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
状态模式的介绍就到此为止了,如有疑问欢迎留言。

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

行为型_备忘录模式(Memento)

设计模式12:状态模式

大话设计模式读书笔记--12.状态模式

State 状态模式

我的设计模式:备忘录模式

23种设计模式(16):状态模式