状态模式
1.什么是状态模式
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类,(State Pattern)是设计模式的一种,属于行为模式。
这正是应验了我们那句话,有些人一旦发生过什么事以后,就像变了个人似的,这句话其实与状态模式有异曲同工之妙。
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
2.类图
image.png类图中包含三个角色。
-
Context:它就是那个含有状态的对象,它可以处理一些请求,这些请求最终产生的响应会与状态相关。
-
State:状态接口,它定义了每一个状态的行为集合,这些行为会在Context中得以使用。
-
ConcreteState:具体状态,实现相关行为的具体状态类。
如果针对刚才对于人的状态的例子来分析,那么人(Person)就是Context,状态接口依然是状态接口,而具体的状态类,则可以是睡觉,上班,休息,这一系列状态。
3.代码
首先我们先定义一个State抽象状态类,里面定义了一个接口以封装于Context的一个特定状态相关的行为:
/**
* 抽象状态类
*/
public abstract class State {
public abstract void Handle(Context context);
}
接着再去声明一个ConcreteState具体状态类,每一个子类实现一个与Context的一个状态的相关的行为。
public class ConcreteStateA extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateB()); //设置A的下一个状态是B
}
}
class ConcreteStateB extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateA()); //设置B的下一个状态是A
}
}
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
/**
* 定义当前的状态
*/
public class Context {
State state;
public Context(State state) { //定义Context的初始状态
super();
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
System.out.println("当前状态为"+state);
}
public void request(){
state.Handle(this); //对请求做处理并且指向下一个状态
}
}
4.使用场景与策略模式区别
使用场景
策略模式:
策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
状态模式:
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
区别
策略模式:策略模式的客户端必须对所有的策略类相当了解,明确当前场景下各种策略的利弊,权衡在当前场景下应该使用哪种策略,也就是是说策略类对客户端是暴露的
状态模式:状态模式依赖于其状态的变化时其内部的行为发生变化,将动作委托到代表当前状态的对象,对外表现为类发生了变化。