上午状态号,中午想睡觉,下午渐回复,加班苦煎熬。其实是一种状态的变化,不同的时间,会有不同的状态。
![](https://i-blog.csdnimg.cn/blog_migrate/335ba48fbe69d638c7d6d1b0ac436654.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f86b75512e9190a41850b6b0e9cec731.png)
MartinFowler曾在《重构》中写过一个很重要的代码坏味道,叫做“Long Method”,方法如果过长其实极有可能是坏味道了。
‘Work(工作)’类的‘WriteProgram(写程序)’方法很长,而且又很多的判断分支,这也就意味着它的责任过大了。无论是任何状态,都需要通过它来改变,这实际上是很糟糕的。
面向对象设计其实就是希望做到代码的责任分解。
这个类违背了‘单一职责原则’
由于‘WriteProgram(写程序)’的方法里有这么多判断,使得任何需求的改动或增加,都需要去更改这个方法了,比如,你们的老板也感觉加班有些过分,对于公司的办公室管理以及员工的安全都不利,于是发了一通知,不管任务再多,员工必须在20点之前离开公司。这样的需求很合理,所以要满足需求你就得更改这个方法,但真正要更改的地方只涉及到17点到22点之间的状态,但目前的代码却是对整个方法做改动的,维护出错的风险很大。
这样写方法违背了“开放-封闭原则”
应该把这些分支想办法变成一个又一个的类,增加时不会影响其他类。然后状态的变化在各自的类中完成。
二、状态模式
状态模式(State),当一个对象的那种状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式注意解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。
把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
![](https://i-blog.csdnimg.cn/blog_migrate/b588924d9972a96b88f96a953042b8a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c088f204e33978b17cc63079f44f9344.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e4c58a4e25cd153fc3ae14a537dadaf2.png)
三、状态模式的好处与用处
好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展,就像最早说的刻板印刷一样,任何改动和变化都是致命的。
状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
什么时候应该考虑使用状态模式呢?
当一个对象的行为取决于它的状态,并且它必须在允许时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
另外如果业务需求某项业务又多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类。这样这些对象就可以不依赖于其他对象而独立变化了,某一天客户需要更改需求,增加或减少业务状态或改变状态流程,都不是困难的事。
客户端代码,没有任何改动。但我们的程序却更加灵活易变了。
此时的代码,如果要完成“员工必须在20点之前离开公司”,只需要增加一个‘强制下班状态’,并改动一些‘傍晚工作状态’类的判断就可以了。这是不影响其他状态的代码的。