策略模式
第一个模式:策略模式
1.1 问题引入
目标:我们设计了一个鸭子超类,现在有很多鸭子会继承这个超类的行为;同时我们希望有一些鸭子具有不同的行为,比如说能飞翔;
1.2实现方案1:
利用继承来实现Duck的行为。
对于子类中的各种鸭子,如果有不同的行为,需要Override超类的行为;
利用继承的方法会出现以下的结果:
实现方案2:因为并不是所有的鸭子都会叫或者飞翔,所以可以考虑将其提取出来,作为接口提供给子类鸭子;
这种方法的特点:
1.虽然Flyable与Quackable接口可以解决“一部分”问题,但是却造成代码无法复用。
设计原则:找到应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
设计方案3:我们知道Duck类内的fly()和quack()会随着鸭子的不同而改变。
为了将这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建议一组新类来代表每个行为。
设计原则:针对接口编程,而不是针对实现编程
现在我们来实现鸭子的行为:
这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用了,因为这些行为类已经与鸭子无关了。
特点:有了继承的“复用”好处,却没有继承所带来的包袱。
Dumb question:
关键在于,鸭子现在会将飞行和咕咕叫的行为“委托”别人处理,而不是使用定义在Duck类(或子类)内的咕咕叫和飞行方法。
实现类图如下所示:
扩张:我们向动态的设定鸭子的行为!我们向通过鸭子子类中动态地设定鸭子的行为,而不是在鸭子的构造器里实例化。
解决方案: 在Duck类中加入两个设定方法即可
“有一个”关系:每一个鸭子都有一个FlyBehavior和一个QuackBehavior,好将飞行和咕咕叫行为委托给他们代为处理。鸭子的行为不是通过继承来的,而是通过和适当的对象“组合”来的。
设计原则:多用组合,少用继承
总结:
引入策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。