首页 > 代码库 > 设计模式学习笔记(十七:状态模式)

设计模式学习笔记(十七:状态模式)

1.1概述

    允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。这就是状态模式的定义。

    一个对象的状态依赖于它的变量的取值情况,对象在不同的运行环境中,可能具有不同的状态。在许多情况下,对象调用方法所产生的行为效果依赖于它当时的状态。

  例如,一个温度计(Thermometer)类的实例:温度计类通过调用方法showMessage()显示有关信息时,需要根据当前自己温度(temperature)变量的值来显示有关信息,即根据自己的状态来决定showMessage()方法所体现的具体行为,这就要求showMessage()方法中有许多条件分支语句,例如:

public void showMessage(){
    if(temperature <= -20){
        System.out.println("现在是低温"+temperature);
     }
    if(temperature >= 30){
        System.out.println("现在是高温"+temperature);
    }
}

  我们注意到showMessage()方法的行为依赖于temperature的大小,这就使Thermometer类的实例在应对需求变化时缺乏弹性,不能很好地满足用户的需求。例如,有些用户可能需要温度计当其temperature的值大于60显示某些重要的信息;有些用户当其温度temperature的值在1825之间显示重要的信息。显然为达到上述要求,必须修改上面的代码才可以满足用户需求,者显然不是人们喜欢做的。

  现在我们需要重新考虑温度计(Thermometer)类的设计,发现温度计类中因用户需求变化而需要修改的代码都和对象的状态有关,即与温度的大小有关,因此,按照面向抽象、不面向实现的设计原则,应当将对象的状态从当前对象中分离出去,即将一个对象的状态封装在另外一个类中。现在,设计一个抽象类:TemperatureState类,该类规定了显示和温度有关的信息的方法showTemperature()。具体类关系图如下图一所示:

 技术分享

 

图一:封装对象的状态

    Thermometer类包含ThermometerState类声明的若干个变量,表面Thermometer类的实例:温度计类可以将任何温度计状态类的子类的实例作为自己的状态,而且温度计类的实例可以把和状态有关的请求委派给所维护状态的对象。

    状态模式的关键是将对象的状态封装成为独立的类,对象调用方法时,可以委托当前对象所具有的状态调用相应的方法,是当前对象看起来好像修改了它的类。

 

1.2模式的结构

状态模式包括以下三种角色:

(1)环境(Context):环境是一个类,该类含有抽象状态(State)声明的变量,可以引用任何具体状态类的实例。用户对该环境(Context)类的实例在某种状态下的行为感兴趣。

(2)抽象状态(State):抽象状态是一个接口或抽象类。抽象状态中定义了与环境(Context)的一个特定状态相关的若干个方法。

(3)具体状态(Concrete State):具体状态是实现(扩展)抽象状态(抽象类)的实例。

状态模式结构的类图如下图二所示:

 技术分享

 

图二:状态模式的类图

 

 

1.3状态模式的优点

1)使用一个类封装对象的一种状态,很容易增加新的状态。

2)在状态模式中,环境(Context)中不必出现大量的条件判断语句。环境(Context)实例所呈现的状态变得更加清晰、容易理解。

3)使用状态模式可以让用户程序很方便地切换环境实例的状态。

4)使用状态模式不会让环境的实例中出现内部状态不一致的情况。

5)当状态对象没有实例变量时,环境的各个实例可以共享一个状态对象。

 

1.4适合使用状态模式的情景

1)一个对象的行为依赖于它的状态,并且它必须在运行时根据状态改变它的行为。

2)需要编写大量的条件分支语句来决定一个操作的行为,而且这些条件恰好表示对象的一种状态。

设计模式学习笔记(十七:状态模式)