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