状态模式

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象为有状态的对象。对象拥有不同的状态,往往会行使不同的行为。对象从事先定好的一系列值中取出。当一个这样的对象与外部事件产生互动时,其内部状态会改变,从而使得系统行为也随之发生变化。

面临问题:

在软件构建过程中,某些对象的状态如果改变,其行为也随之发生改变,如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明地改变对象的行为?但又不会为对象操作和状态转化之间引入紧耦合?

也就是说,因为对象的状态是不断变化的,所以对象的行为也会发生变化,我们想根据运行时的状态,动态的改变对象的行为,这时候应该怎么办呢?加入这时候,对象的操作和状态之间是采用紧耦合的话,使用if esle语句,每次新增加状态的时候,都要对对象类进行修改,而这时如果对象很多,就要对每个对象进行修改,这时应该怎样才能松耦合呢?即对象的操作和状态转换之间。即改变对象的状态,但不会修改对象,而且对象的行为会随之改变。怎样做呢?


解决方案

面向对象的设计原则是分割不同的责任以委派给不同的对象。State模式解决的责任分割和责任委派是行为责任和做状态判断的逻辑责任的分割和委派。

State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的----即要么彻底转换过来,要么不转换。如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。

也就是说,一个状态对应着一个对象,对象的状态的改变,通过在状态类中有对象的实例,具体状态实现类通过调用对象的设置状态方法,设置不同的状态,这样就会完成状态的转换。(建议直接参考代码,自己搜索下)。




Context(环境类)
 定义客户感兴趣的接口
维护一个ConcreteState子类的实例,这个实例定义当前状态。

环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作。

有setState方法。具体的状态类,会调用context中的setState方法,实现状态切换。

State(抽象状态类)
 定义一个接口以封装与Context的一个特定状态相关的行为。注意和state是双向关联箭头。这样才能具体state状态,根据条件,调用context中的setState方法,实现状态切换。

抽象状态类可以是抽象类,也可以是接口,不同状态类就是继承这个父类的不同子类,状态类的产生是由于环境类存在多个状态,同时还满足两个条件:这些状态经常需要切换,在不同的状态下对象的行为不同。因此可以将不同对象下的行为单独提取出来封装在具体的状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,对象看起来似乎修改了它的类,而实际上是由于切换到不同的具体状态类实现的。由于环境类可以设臵为任一具体状态类,因此它针对抽象状态类进行编程,在程序运行时可以将任一具体状态类的对象设臵到环境类中,从而使得环境类可以改变内部状态,并且改变行为。
ConcreteState (具体状态类)
 每一个子类实现一个与Context的一个状态相关的行为


应用:

1.一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

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


相关模式:

Flyweight模式解释了何时以及怎样共享状态对象
状态对象通常是Singleton

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值