HeadFirst设计模式读书笔记之策略模式
程序员文章站
2022-05-04 10:17:41
1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超类,实现自己的display()方法来表现鸭子的行为,像下面这样: 2. 但如果要加一个可以吃火锅的 ......
1. 例子
1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在
超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超类,实现自己的display()方法来表现鸭子的行为,像下面这样:
2. 但如果要加一个可以吃火锅的鸭子呢,类就会变成这样:
可以看到,每添加一个新的鸭子就要修改超类一次,而不需要这些多余行为的鸭子不得不
继承这些多余的方法,这样每只鸭子都是全能的,一点差异都没有,代码失去了意义,这样做既不安全,又不方便扩展.想想,每增加一个鸭子,就要
修改超类一次,如果有成千上万种鸭子岂不麻烦死了.总结一下,有以下几个缺点:
1. 代码在多个子类重复
2. 运行时的行为不容易改变
3. 难以知道所有鸭子的全部行为(有些鸭子的行为可能定义在子类,并且无法重用)
4. 牵一发而动全身,改了超类,其他鸭子继承的行为也会改变
3. 新的思路重构代码
1. 将容易变化的需求与不变化的需求分开处理
2. 将鸭子和鸭子的各种行为分开处理,通过接口来组合他们,这就是针对接口编程
3. 让鸭子持有定义行为的接口,将鸭子的行为''委托' 给别人处理,不直接定义在鸭子类中
4. 将鸭子的行为通过接口来实现,运行时通过多态来指定具体实现
2. 关键代码
/** * @author: lisa * @date: 2018/11/16 10:03 */ public interface flybehavior { // 飞飞飞 void fly(); }
/** * @author: lisa * @date: 2018/11/16 10:04 */ public interface quackbehavior { // 呱呱叫 void quack(); }
/** * @author: lisa * @date: 2018/11/16 10:06 */ public abstract class duck { flybehavior flybehavior; quackbehavior quackbehavior; public duck(flybehavior flybehavior, quackbehavior quackbehavior) { this.flybehavior = flybehavior; this.quackbehavior = quackbehavior; } public duck() { } public abstract void display(); public void setflybehavior(flybehavior flybehavior){ this.flybehavior = flybehavior; } public void setquackbehavior(quackbehavior quackbehavior) { this.quackbehavior = quackbehavior; } public void performquack() { quackbehavior.quack(); } public void performfly() { flybehavior.fly(); } public void swim() { system.out.println("all ducks float, even decoys!"); } }
public class flywithwings implements flybehavior { @override public void fly() { system.out.println("鸭子在贡嘎山脉广袤的森林中飞行"); } }
/** * @author: lisa * @date: 2018/11/16 10:18 */ public class quack implements quackbehavior { @override public void quack() { system.out.println("春天到了,鸭子嘎嘎叫"); } }
/** * @author: lisa * @date: 2018/11/16 10:54 */ public class flyrocketpowerd implements flybehavior { @override public void fly() { system.out.println("火箭式助推飞行装置,启动!"); } }
/** * @author: lisa * @date: 2018/11/16 10:18 */ public class squeak implements quackbehavior { @override public void quack() { system.out.println("鸭子发出了吱吱的娇嗔"); } }
/** * @author: lisa * @date: 2018/11/16 10:37 */ public class miniducksimulator { public static void main(string args[]) { duck mallard = new mallardduck(new flywithwings(),new quack()); mallard.performquack(); mallard.performfly(); mallard.setflybehavior(new flyrocketpowerd()); mallard.setquackbehavior(new squeak()); mallard.performfly(); mallard.performquack(); } }
结果: 春天到了,鸭子嘎嘎叫 鸭子在贡嘎山脉广袤的森林中飞行 火箭式助推飞行装置,启动! 鸭子发出了吱吱的娇嗔
3. 学到的设计原则
- 找出应用中可能需要变化之处,把他们独立出来,不和那些不需要变化的代码混到一起
- 针对接口编程,而不是针对实现编程
- 多用组合,少用继承
4. 策略模式的定义
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
上一篇: 原型模式 prototype 创建型 设计模式(七)
下一篇: 抽象工厂模式 创建型 设计模式(四)