State模式将所有与一个特定的状态转换和状态对应的行为都放入一个状态子对象中,Context和State之间是双向关联的,因为Context管理了各个State子类,状态和相应逻辑虽然在State中,但是State之间通信需要通过Context类。因为所有与状态相关的代码都存在于某一个State子类中, 所以通过定义新的子类可以很容易的增加新的状态和转换。 State模式提供了一个更好的方法来组织与特定状态相关的代码。决定状态转移的逻辑不在单块的if或s witch语句中, 而是分布在State子类之间。
State的UML类图:
电梯开关,运行停止,逻辑的State模式的UML类图,参考:http://blog.csdn.net/hguisu/article/details/7557252
- class Client {
- public static function main() {
- $context = new Context();
- $context->setLiftState(new ClosingState());
- $context->open();
- $context->close();
- $context->run();
- $context->stop();
- }
- }
State和Strategy区别:
Strategy客户是需要知道逻辑子类的提供可选策略;State不需要,内部会根据状态跳转,状态子类中状态迁移和状态处理是核心。
策略(如促销一种商品的策略)和状态(如同一个按钮来控制一个电梯的状态,又如手机界面中一个按钮来控制手机)是两种完全不同的思想。当我们对状态和策略进行建模时,这种差异会导致完全不同的问题。例如,对状态进行建模时,状态迁移是一个核心内容;然而,在选择策略时,迁移与此毫无关系。另外,策略模式允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有。
把各个状态和相应的实现步骤封装成一组简单的继承自一个接口或抽象类的类,通过另外的一个Context来操作他们之间的自动状态变换,通过event来自动实现各个状态之间的跳转。在整个生命周期中存在一个状态的迁移曲线,这个迁移曲线对客户是透明的。
State和Commmand模式区别:
State是本来是Context自身状态分离出来的,Context关联State抽象接口,拥有每个状态切换设置状态,并执行公共接口。
Command是只是在命令发出者和接受者之间做了个中转,本来有命令的发出者InvokeControl, 和命令的接受者,Command模式只是通过Command定义抽象接口,Receiver需要注册到具体的Command子类,然后Command子类注册给InvokerControl类,InvokerControl调用委托给Command的执行接口即可,也就是Command模式只是在命名调用者和处理者之间插入了一层中转。所以State模式和Command模式是两个出发点不一样的。
State和Chain of Rain区别:
职责链模式和状态模式都可以解决If分支语句过多,从定义来看,状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定),而职责链模式是多个对象之间的改变(多个对象之间的话,就会出现某个对象不存在的现在,就像我们举例的公司请假流程,经理可能不在公司情况),这也说明他们两个模式处理的情况不同。这两个设计模式最大的区别就是状态模式是让各个状态对象自己知道其下一个处理的对象是谁。而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。
State模式的总结:
状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。
State状态模式在一个Context类下并不能真正的简化和提高可拓展性,只是用类来做抽离了状态和状态处理逻辑可以让原来的Context类更简单些,职责更分离些;因为原来对象的每个行为都要判断下状态,现在是每个状态都要维护多个行为,且增加了新的状态情况下,原来是在每个行为中对新的状态做判断,现在是每个原有的状态都要对新增状态的判断和跳转执行; 其中判断是基于当前状态的,判断通过进行跳转执行是通过Content类的,所以是双向关联或依赖的。
State状态模式在多个Context可以对应一个State状态模式下,才能真正的降低冗余,利于可维护性。