设计模式——State模式(第三版)

一,动机

当一个对象的状态发生改变时,有时候我们会希望它的行为也会随着状态的改变而改变。

比如一个人(对象),没钱的时候(状态)晚上只能吃泡面(行为),但是当他有钱了(状态发生改变),那么他就可以大口吃肉了(行为也发生改变)。

这个时候就需要一种方式,在对象的状态发生改变的时候也同样改变它的行为。

State模式就是这样一种模式,允许一个对象在它的内部状态发生改变的时候也改变它的行为,因为行为方法变得不同了,就好像这个类也发生了改变一样。

二,介绍
1.参与者

Context 环境,上下文,定义了用户需要调用的方法,并且维护了ConcreteState的实例,该实例定义了Context的状态。

State 状态,抽象的状态类,用接口定义一个Context在某种状态下的行为。

ConcreteState 具体的状态实现类,实现一个与Context状态相关的行为。

2.协作关系

Context 将与状态有关的请求委托给ConcreteState来处理。

Context 可以将自身作为一个参数传给处理该请求的 ConcreteState 对象。

Context 是主要的用户入口,用户只需与Context打交道,而无需考虑 ConcreteState 。

Context 和 ConcreteState 都可以决定哪个状态是另一个状态的后继状态,以及在什么条件下进行状态转换。


State模式
代码示例

public interface State{
    public void eat();
}

public class PoorState implements State{
    public void eat() {
        System.out.println("吃泡面");
    }
}

public class RichState implements State{
    public void eat() {
        System.out.println("吃山珍海味");
    }
}



public class Person {

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

    public void eat(){
        this.state.eat();
    }
}

三,使用场景
对象的行为取决于自身的状态,并且需要在运行时根据自身的状态来决定自己的行为。
当一个操作包含多个条件分支,并且这些分支的条件判断都取决于对象的状态时,可以使用state模式将分支放入类中,使得对象根据状态的不同调用不同的方法。

四,效果
1.将与状态有关的行为局部化,将不同状态的行为分割开。

State模式将所有与某个状态有关的行为都放到一个子类中,因此可以轻松的通过定义新的子类来追加新的状态和转换。对于一般的通过if...else...等条件语句来控制对象的行为,会导致在状态很多的情况下,出现大量的条件分支,从而使整个代码变得庞大,也更难阅读和维护。增加一个新的状态可能会导致要改变多个操作。

State 模式解决了这些问题,将不同状态的行为放到不同的子类中,从而减少了分支。但于此同时,为不同的状态创建不同的子类,也会导致子类的数目变多,而对于单个类中的代码不够紧凑,出现类的数量很多,但是每个类里的代码逻辑却很少的情况。

2.使状态转换显式化

如果一个对象仅通过内部的属性来定义状态的话,那么状态的转换仅表现为变量的赋值,不够明确,容易发生状态不一致的情况。比如,一个属性记录这个人是有钱的,另一个属性却记录了这个人只有1元钱,就会出现状态不一致的情况:有钱,却只有1元钱。

使用State模式可以避免这个情况发生,因为对于Context而言,状态的转换是原子的,需要为重新绑定State变量。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容