定义
对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
一个函数原本有很多判断语句,现在把判断语句中的每一种状态封装成一个类,每一个状态类中均有一个handle()函数,该函数能对当前状态做出处理,并且能指明不能处理时的下一个状态类。
优点:
- 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
- 减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
- 有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换,遵循了“开放-封闭原则”。
缺点:
- 状态模式的使用必然会增加系统的类与对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
应用场景:
当一个函数中判断分支很多时,就需要使用状态模式。
模式结构
- 将一个原本的判断结构封装成一个个状态类,每个状态类都有函数handle(Context);
该函数对本状态作出处理,当无法处理时,将context肚子中的成员变量state改成能处理的那个状态类的对象,并执行context的request()函数;
handle()函数实现如下:
public void handle(Context Context){
//判断是否能处理
if(本类能处理){
进行处理;
}
//本类不能处理时
else{
//将context的state变量设为能处理状态类的对象
context.setState(new ConcreteStateB());
//执行context中的request,让下一个状态类处理
context.request();
}
}
- 创建一个Context类,它是提供给客户端执行整个状态模式的接口;
Context类中含有State类型的成员变量state,还有一个handle()函数,该函数用于执行state中的request()函数。
class Context(){
private State state;
public void request(){
this.state.handle();
}
}
- 当客户端调用context的request()函数时,request调用当前context肚子里的那个state的handle函数,如果能处理就处理掉,如果不能处理就将context的state设为能处理的那个状态类,然后再调用request函数。
然后新的处理函数又被执行,直到遇到能执行的处理类为止。
状态模式与职责链模式的异同?
相同点:状态模式和职责链模式都是将判断语句中的每一个判断分支封装成一个个类。
不同点:状态模式中,每个状态类中既包含了符合条件时的处理方法,也在不符合条件时指明下一个状态类,然后执行该状态类中的处理函数;而在职责链模式中,每一个处理类的处理函数中只有处理当前状态的方法,若不能处理时下一个处理类是由客户端指定的。
综上所述:状态模式的判断流程是在低层模块中定义好的,职责链模式的处理流程是让用户自己设置的。
参考:
(1)三分钟理解“状态模式”——设计模式轻松掌握 https://blog.csdn.net/u010425776/article/details/48244587
(2)状态模式(详解版) http://c.biancheng.net/view/1388.html