设计模式——状态模式

来源:互联网 发布:mac 命令行上传文件 编辑:程序博客网 时间:2024/06/07 03:54

状态在我们的生活中是很常见的,比如我们交通使用的红绿信号灯,有红、黄、绿三种状态。其实我们的衣食住行都是状态,比如火车的启动,运行,暂停,状态几乎是无处不在。下面我们来看一个大家再熟悉不过的状态图
这里写图片描述
想必大家也都知道这几种状态的意义了。其实在我们程序里面状态也是很常见的,比如我们经常使用的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();

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

0 0