首页c++设计模式 › 状态模式——水之三态

状态模式——水之三态

什么是状态?

状态即事物所处的某一种形态。状态模式是说一个对象在其内部状态发生改变时,其表现的行为和外在属性不一样,这个对象看上去就像是改变了它的类型一样。因此,状态模式又称为对象的行为模式。

如我们生活中经常见到的水,就有三种不同状态冰、水、水蒸汽,三种状态所表现的外在性质完全不一样:1.冰,质坚硬,无流动性,表面光滑;2.水,具有流动性;3.水蒸汽,肉眼看不见,却存在于空气中,质轻。这三种状态特性是不相差巨大?简直就不像是同一种物质的,但事实却是不管它是在什么状态,其特里组成都是一样的,都是水分子(H2O)。
1438488729414_414

以水为例说状态模式

你还记得初中物理学书上的这副图吗?水有三种状态:固、液、气,三种状态表现出不同的特性和行为,它们之间的转换也伴随着一着热力学的现象。现在要用程序来模拟水的三种状态和相互转换,要如何实现呢?
1438488939368_368

水之三态

我们从对象的角度来考虑会有哪个类,首先不管它是什么状态始终是水(H2O),所以会有一个Water类;而它又有三种状态,我们可以定义三个状态类:SolidState、LiquidState、GaseousState;从SolidState、LiquidState、GaseousState这三个单词中我们会发现都有一个State后缀,于是我们会想它们之间是否有一些共性,能否提取出一个更抽象的类,这个类就是状态类(State)。这些类之间的关系大致如下:
1438496070243_243

水与状态之间的类图关系

Ok,我们已经知道了大概的关系,那就开始Coding实现吧,在实现的过程中不断完善……
Water.h:

State.h:

Water.cpp:

State.cpp:

测试代码:

结果如下:

好了,上面的程序已经完美地帮我们完成了水的三种状态及其转变的模拟。我们再来整理一个上面的代码中的类图结构,如下图:
1438524248040_40

水与状态之间的类图关系

SolidState、LiquidState、GaseousState三个类用了单例的模式,因为状态只需要一个对象就可以了,这三个类中CGarbo是一个内部类,只为了释放静态对象,关于单例模式的用法,可以参考《生活中的单例——不是单身》。Water中的ChangeState可方便地进行三种状态之间的转换。

水之三态升级版

在本篇文章发表之后,有读者提出说上面的例子并不太好:因为void Water::SetTemperature( int nTemperature )方法不符合程序设计中的开放封闭原则,如果再加一个状态(State),则要在SetTemperature中再一个if else判断。

这位读者说的确实有道理,这里的SetTemperature确实不符合开放封闭原则,在这要感谢[reply]FRcheng[/reply]提出了宝贵的意见和对此的看法。但我依然觉得水的三种状态是状态模式的典型,因为这特别贴近生活,一说就懂。会出现不符合开放封闭原则的情况是因为我程序写的完善,于是经过思考后又修改了一个新的版本,这版本即符合开发封闭原则,又满足了FRcheng提到的“状态可变化,也可增加”的需求。
State.h:

State.cpp:

Water.h:

Water.cpp:

测试代码:

结果:

状态模式总结

通过上面一个生活中的例子,应该很容易能明白状态模式吧!其实也简单,其结构关系如下:
1438525499813_813

状态模式结构图

Behavior是不同一个对象在不同状态下的行为(如DoWork),ChangeState用于改变对象的状态,Request则是操作请求(如RiseTemperature和ReduceTemperature)。

发表评论