状态模式

状态模式定义:对象行为的变化是由于状态的变化引入,那么即当内部状态发生变化的时候,就会改变对象的行为,而这种改变视乎就改变了整个类。

结构

很多人在说状态模式的时候总拿策略模式来进行对比,可能他们的类图会有一点类似。最根本的差异在于策略模式是在求解同一个问题的多种解法,这些不同解法之间毫无关联;状态模式则不同,状态模式要求各个状态之间有所关联,以便实现状态转移

1、Context
定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
2、State
定义一个接口以封装与Context的一个特定状态相关的行为。
3、ConcreteStatesubclasses
每一子类实现一个与Context的一个状态相关的行为。

应用场景

1、一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。 这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

优缺点

优点:
1、降低程序的复杂度;
2、提高程序的可维护性;
3、状态机模式体现了开闭原则和单一职责原则。每个状态都是一个子类,增加状态就要增加子类;修改状态只要修改一个类就行了。

缺点:
使用状态机子类会增多,也就是类膨胀,这点需要程序员在开发中自己衡量。

代码实现

定义State

1
2
3
4
5
//定义和Context中的状态相对应的行为
public interface State {
//获取天气情况
String getState();
}

定义ConcreteStatesubclasses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Sunshine implements State{

@Override
public String getState() {

return "晴天";
}

}
class Rain implements State{

@Override
public String getState() {

return "下雨";
}

}

定义Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//定义当前的状态
public class Context {

private State state;

public State getState() {
return state;
}

public void setState(State state) {
this.state = state;
}
public String stateMessage(){
return state.getState();
}
}

调用类

1
2
3
4
5
6
7
8
9
10
11
12
public class StateTest {

public static void main(String args[]){
Context context=new Context();
context.setState(new Rain());

System.out.println(context.stateMessage());

context.setState(new Sunshine());
System.out.println(context.stateMessage());
}
}

和策略模式的区别和联系

区别:
状态模式将各个状态所对应的操作分离开来,即对于不同的状态,由不同的子类实现具体操作,不同状态的切换由子类实现,当发现传入参数不是自己这个状态所对应的参数,则自己给Context类切换状态;而策略模式是直接依赖注入到Context类的参数进行选择策略,不存在切换状态的操作联系。

联系:
状态模式和策略模式都是为具有多种可能情形设计的模式,把不同的处理情形抽象为一个相同的接口,符合对扩展开放,对修改封闭的原则。还有就是,策略模式更具有一般性一些,在实践中,可以用策略模式来封装几乎任何类型的规则,只要在分析过程中听到需要在不同实践应用不同的业务规则,就可以考虑使用策略模式处理,在这点上策略模式是包含状态模式的功能的,策略模式是一个重要的设计模式。