状态模式
将每个状态的行为局部化到它自己的类中
将容易产生问题的if语句删除,以方便日后的维护。
让每一个状态”对修改关闭”、让糖果机”堆扩展开放”,因为可以加入新的状态类
创建一个新的代码基和类结构,这更能映射万
能糖果公司的图,而且更容易阅读和理解
综述
定义
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
解释:
- 允许对象在内部状态改变时改变它的行为
- 将状态封装称为独立地类,并将动作委托到代表当前状态的对象,行为会随着内部状态为改变。
- 对象看起来好像修改了它的类
- 如果说你使用的对象能够完全改变它的行为,那么你会觉得,这个对象实际上是从别的类实例化而来的。实际上。是使用组合通过简单引用不同的状态对象来造成类改变的假象。
类图
要点
- 状态模式允许一个对象基于内部状态而拥有不同的行为。
- 和程序状态机(PSM)不同,状态模式用类代表状态
- Context会将行为委托给当前状态对象
- 通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。
- 状态模式和策略模式有相同的类图,但是它们的意图不同
- 策略模式通常会用行为或算法来配置Context
- 状态模式允许Context随着状态的改变而改变行为
- 状态转换乐意由State类或Context类控制
- 使用状态模式通常会导致设计中的类数目大量增加
- 状态类可以被多个Context实例共享
注意事项
状态转换放在Context还是状态类中
当状态转换时固定的时候,就适合放Context中;当装换时更动态的时候,通常就会放在状态类中
在做这个决策的同时,也等于是在为另一件事情做决策:在系统进化是,究竟哪个类是对修改封闭的(Context还是状态类)。
客户不允许和状态交互
如果想共享状态:
需要把每个状态都指定到静态的实例变量中。如果你的状态需要利用到Context中的方法或者实例变量,你还必须在每个Handler()方法内传入一个Context的引用。
使用状态模式的类会很多
如果你有一个应用,它有很多状态,但是你决定不将这些状态封装在不同的对象中,那么你就会得到巨大的、整块的条件语句。这会让你的代码不容易维护和理解。通过使用许多对象,你可以让状态变得很干净,在以后理解和维护它们时,就可以下很多的工夫。
状态模式的State选择抽象类还是接口?
使用接口:如果没有共同的功能可以放进象类中。
使用抽象类:以后需要在抽象类加入新的方法时就很容易,不需要打破具体状态的实现。
代码实例
Context类(糖果机)
public class GumballMachine
{
private State _soldOutState;
private State _noQuarterState;
private State _hasQuarterState;
private State _soldState;
private State _WinnerState;
private State _state;
private int _count = 0;
public State State { get => _state; set => _state = value; }
public State SoldOutState { get => _soldOutState;