说到策略模式,我们最早想到的就是商店的收银方式:不满100,正常收费;超过100不满300,超过的部份打8折;超过300,全价9折!
解决这个问题最最普通的方法就是大量的If…Else…,而它带来的就是无情的难以保护,每次条件变更都会修改原代码,严重违背了开闭原则。
不言而喻,策略模式的解决方式就是封装了1系列平行且复杂的实现方式,在不同的场景下,我们选择1个最合适的方案。
来看它的类图
图⑴ 《大话设计模式》
图⑵ 《HeadFirst》
第1张是《大话设计模式》里的,第2张是《HeadFirst》里的1个具体的例子。
第1个比较简单,也最典型。不过量说了。
来看第2个,它实际上是经过了1系列演化的。原来的“飞行”接口是封装在Duck里的,也就是说所有的鸭子都必须会飞才行。但实际上有的鸭子只能跑,那怎样办?就只能把“飞行”抽取出来,构成1个单独的接口,让会飞的鸭子去实现。
这样还有问题,如果有的鸭子能直接飞,有的鸭子需要助跑飞,那怎样办?每一个类型的鸭子都需要重写飞行方法,这样也不适合,所以就写出“飞行”接口实现的子类,再让符合该类型的鸭子去调用。实质就是1种多态。
策略就体现在它封装了不同的飞行方式,可供客户端去选择1个最好的、最适合的去调用。
状态模式:当1个对象的内在状态变化时允许改变起行动,这个对象看起来像是改变了其类。
来看它的类图:
状态模式主要突出了两个字:“改变”,对象的状态决定了状态的行动,我们精神亢奋的时候,就努力的工作,努力的工作就致使了我们身心疲惫,身心疲惫就致使我们的行动是需要休息。从这里我们可以看出,事物的内在状态决定了事物所做出的行动,而事物的行动又会改变我们事物的状态,二者在不断的相互影响,然后实现状态的转换。
状态模式主要解决的是当控制1个对象状态转换的条件表达式过于复杂的情况。把状态的判断转移到表示不同状态的1系列类中,可以把复杂判断简化。
当1个状态的行动取决于他的状态,并且他必须在运行时刻根据状态改变他的行动时,可以斟酌使用状态模式。
比较:从上面这几点,我们可以看出策略模式和状态模式的利用场景有很大的不同:1个是封装1系列平行且复杂多变的实现方式,1个是实现把对象的内在状态的变化封装起来,用外部行动来表现出来。
总之,虽然2者的类图很相似,但实际上解决的是不同情况的两种场景问题,需要我们去实际分析和判断。不同设计模式之间存在不同的设计思路,相似的更需要我们去仔细比较,每次学习都是1次进步和再认识。