TypechoJoeTheme

IT技术分享

统计

状态模式(State)——23种设计模式之行为型模式

2016-04-23
/
0 评论
/
690 阅读
/
正在检测是否收录...
04/23

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象为有状态的对象。

对象拥有不同的状态,往往会行使不同的行为。 对象从事先定好的一系列值中取出。当一个这 样的对象与外部事件产生互动时,其内部状态会改变,从而使得系统行为也随之发生变化。

在软件构建过程中,某些对象的状态如果改变,其行为也随之发生改变,如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明地改变对象的行为?但又不会为对象操作和状态转化 之间引入紧耦合?

面向对象的设计原则是分割不同的责任以委派给不同的对象。State模式解决的责任分割和责任委派是行为责任和做状态判断的逻辑责任的分割和委派。

一、类图表示

状态模式涉及到Context(环境类),State(抽象状态类),ConcreteState (具体状态类)等角色

  • ①、Context(环境类):定义客户感兴趣的接口,维护一个ConcreteState子类实例,这个实例定义当前状态。
  • ②、State(抽象状态类):定义一个接口以封装与Context的一个特定状态相关的行为。
  • ③、ConcreteState (具体状态类):每一个子类实现一个与Context的一个状态相关的行为

java-state-model-1

二、代码示例

/*
* 状态操作接口,执行上一个下一个的操作,还可以获得当前的状态
* 当然在这可以既执行别的操作,比如开关拨到某个颜色的时候,颜色对应的灯亮
*/

public interface State {

    public  void last(Context c);

    public  void next(Context c);

    public  String getState();


}
/*
* 蓝色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中
* 设置改变后的状态
*/
public class BlueState implements State {

    public String getState() {
        return "blue";
    }

    public void last(Context c) {
        c.setState(new GreenState());
    }

    public void next(Context c) {
        c.setState(new RedState());
    }

}
/*
* 绿色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中
* 设置改变后的状态
*/
public class GreenState implements State {

    public String getState() {
        return "green";
    }

    public void last(Context c) {
        c.setState(new RedState());
    }

    public void next(Context c) {
        c.setState(new BlueState());
    }

}
/*
* 红色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中
* 设置改变后的状态
*/
public class RedState implements State {

    public String getState() {
        return "red";
    }

    public void last(Context c) {
        c.setState(new BlueState());
    }

    public void next(Context c) {
        c.setState(new GreenState());
    }
/*
* 状态管理器,设置初始状态,得到当前状态,
* 提供了两个操作,上一个的操作方法中,调用了当前状态的last方法,将状态管理器的状态更新
* 下一个的操作方法中,调用了当前状态的next方法,将状态管理器的状态更新
*/
public class Context {

    private State state = null;

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void push(){
        state.last(this);
        System.out.println(state.getState());
    }

    public void pull(){
        state.next(this);
        System.out.println(state.getState());
    }

}
/*
* 测试类
*/
public class Test {

    public static void main(String[] args) throws InterruptedException {
        /*
        * 创建一个状态管理器,设置初始状态为红色,
        * 然后就可以执行状态管理器的last或者next方法
        */
        Context c = new Context();
        State redsState = new RedState();
        c.setState(redsState);
        while (true){
            System.out.println("当前状态:"+c.getState().getState());
            System.out.print("上一个状态: ");
            c.push();
            Thread.currentThread().sleep(2000);
        }
    }

}

三、优缺点分析

1、优点

  • ①、State模式分离了状态机的逻辑和动作,动作在Context中实现,而逻辑分布在state类的派生类中,使得二者可以非常容易地独立变化、 互不影响。
  • ②、高效、既有表驱动法的灵活性,又有嵌套switch/case的效率。
  • ③、它将与特定状态相关的行为局部化,并且将不 同状态的行为分割开来
  • ④、它使得状态转换显式化,State对象可被共享

2、缺点

  • ①、state派生类的编写乏味;
  • ②、逻辑分散,无法在一个地方看到整个状态机逻辑,代码维护困难。

四、模式间关系

1、与享元模式的关系

Flyweight模式解释了何时以及怎样共享状态对 象

2、与单例模式的关系

状态对象通常是Singleton

3、与策略模式的关系

  • ①、策略用来处理算法方式变化,而状态则是处理状态变化。
  • ②、对于模式的选择反映出设计者对结构的理解。此刻你把它视为一种状态,如果将来你发觉用Strategy能更 好的说明你的意图,你可以重构它。
  • ③、这两种模式在结构上相似,有时候没有区别,都是通过继承来实现的。所以如果重构变化会较小。
  • ④、Strategy模式用来处理用户算法方案的变化。这些算法方案 之间一般来说没有状态变迁,并且总是从几个算法中间选 取一个。

五、适用场景

一个对象的行为取决于它的状态, 并且它必须在 运行时刻根据状态改变它的行为。

  • ①、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
  • ②、这个状态通常用一个或多个枚举常量表示。
  • ③、通常,有多个操作包含这一相同的条件结构。

六、总结

状态模式在运行时根据对象的状态来透明地改变对象的行为。

  • ①、State模式将每一个条件分支放入一个独立的类中。这使得你可以 根据对象自身的情况将对象的状态作为一个对 象,这一对象可以不依赖于其他对象而独立变 化。
  • ②、State模式将所有与一个特定状态相关的行为都放入 一个State的子类对象中,在对象状态切换时,切换 相应的对象;但同时维持State的接口,这样实现了 具体操作与状态转换之间的解耦。
  • ③、为不同的状态引入不同的对象使得状态转换变得更 加明确,而且可以保证不会出现状态不一致的情况, 因为转换是原子性的----即要么彻底转换过来,要么 不转换。
  • ④、如果State对象没有实例变量,那么各个上下文可以 共享同一个State对象,从而节省对象开销。
朗读
赞 · 0
版权属于:

IT技术分享

本文链接:

https://idunso.com/archives/1977/(转载时请注明本文出处及文章链接)