设计模式-状态模式

定义

状态模式,允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

这个模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象,行为会随着内部状态而改变。

实例

以糖果机为例,自动售卖糖果。

糖果机工作状态流程:

没有25分钱—》投入25分钱—》有25分钱—》转动曲柄—》售出糖果—》发放糖果,如果此时糖果数目等于0,则变成糖果售罄,否则返回没有25分钱状态。

其中,在投入25分钱,未转动曲柄前,可退回25分钱。

在糖果售罄状态时,不能投25分钱。

很明显,这个例子有4个状态:没有25分钱,有25分钱,售出糖果,糖果售罄。

有4个动作:投入25分钱,退回25分钱,转动曲柄,发放糖果。

常规方法是创建状态常量值

final static int SOLD_OUT = 0;
final static int NO_QUARTER = 1;
final static int HAS_QUARTER = 2;
final static int SOLD = 3;

int state = SOLD_OUT;

然后在糖果机中,用if条件一个个判断状态并实现具体逻辑。这样的做法会使代码难以维护,当需求变动时,需要改动这一大块的if代码。

我们可以用状态模式优化,将每一个状态都作为一个类,在状态类中实现自己的行为。Context即糖果机,根据行为切换具体的状态类。

以没有25分状态为例,看修改后的实现:

// 实现统一的State接口
public class NoQuarterState impplements State {
    GumballMachine gumballMachine;
    
    // 通过构造器得到糖果机的引用
    public NoQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    
    // 如果有人投了25分钱,打印消息,并改变机器状态到有25分钱
    public void insertQuarter() {
        System.out.println("You inserted a quarter");
        gumballMachine.setState(gumballMachine.getHasQuarterState());
    }
    
    // 如果没给钱,就不能要求退钱
    public void ejectQuarter() {
        System.out.println("You haven't inserted a quarter");
    }
    
    // 如果没给钱,就不能要求糖果
    public void turnCrank() {
        System.out.println("You turned, but there's no quarter");
    }
    
    // 如果没得到钱,我们就不能发放糖果
    public void dispense() {
        System.out.println("You need to pay first");
    }
}

重新改造糖果机:

public class GumballMachine {
    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    
    State state = soldOutState;
    int count = 0;
}

其他状态的代码,与没有25分状态类似,都在自己的状态类中实现具体行为逻辑。

与策略模式对比

状态模式与策略模式的类图是一样的,它们的区别在于意图不同。

以状态模式而言,我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个。随着时间的流逝,当前状态在状态对象集合中游走改变,以反映出context内部的状态,因此,context的行为也会跟着改变。但是context的客户对于状态对象了解不多,甚至根本是浑然不觉。

而以策略模式而言,客户通常主动指定Context所要组合的策略对象是哪一个。现在,固然策略模式让我们具有弹性,能够在运行时改变策略,但对于某个context对象来说,通常都只有一个最恰当的策略对象。

一般来说,我们把策略模式想成是除了继承之外的一种弹性替代方案。如果你使用继承定义了一个类的行为,你将被这个行为困住,甚至要修改它都很难。有了策略模式,你可以通过组合不同的对象来改变行为。

我们把状态模式想成是不用在context中放置许多条件判断的替代方案。通过将行为包装进状态对象中,你可以通过在context内简单地改变状态对象来改变context行为。

小结

  1. 状态模式允许一个对象基于内部状态而拥有不同的行为。

  2. 和程序状态机(PSM)不同,状态模式用类代表状态。

  3. Context类会将行为委托给当前状态对象。

  4. 通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。

  5. 状态模式和策略模式有相同的类图,但是它们的意图不同。

  6. 策略模式通常会用行为或算法来配置Context类。

  7. 状态模式允许Context随着状态的改变而改变行为。

  8. 状态转换可以由State类或Context类控制。

  9. 使用状态模式通常会导致设计中类的数目大量增加。

  10. 状态类可以被多个Context实例共享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值