在大学的时候,看过一本设计模式的书。那时是上网找的pdf,书名不记得了。但是印象最深刻的是,那本书特别晦涩难懂,翻译的特别拗口。虽然硬着头皮看完了,但是记住的没有多少。
如今,买了一本《Head First 设计模式》,开始重新学习设计模式。边学边记录,算是学习笔记吧。这篇是《Head First 设计模式》学习笔记第一篇:策略模式。
(好吧,我又开了一个坑,能不能坚持写完还另说。)
从问题入手
《Head First 设计模式》书中提到的Duck
的例子非常的形象,我用自己的画重新表述一遍,跟书中略有区别。
- 需要实现一个鸭子
Duck
类,鸭子有一种行为:飞行 - 正常的鸭子会飞,但是玩具鸭不会飞。
我们很自然的想到,实现基类Duck
类,提供一个默认的fly
方法,玩具鸭重写fly
方法,提供一个空实现。
或者是基类不提供fly
方法实现,实现两个子类FlyableDuck
和ToyDuck
,其中FlyableDuck
表示会飞的鸭子,实现fly
方法;ToyDuck
表示玩具鸭,提供空的fly
方法。
就我列出的两点的要求来说,两个方法都可以实现。但有以下缺点:
- 方法一:如果后续新增加一种不会飞的鸭子时,需要关心父类已经实现了对应的
fly
方法,需要主动覆盖fly
方法 - 方法二:如果后续新增一种叫的行为,分为吱吱叫、呱呱叫,飞行行为也分为蜻蜓点水飞行、低空飞行两种,那是不是就得实现四个类表示行为两两组合的鸭子呢?
那么接下来,再提几个要求:
- 鸭子分为普通鸭,池塘鸭,旱鸭,玩具鸭
- 普通鸭会低空飞行,吱吱叫,池塘鸭会蜻蜓点水飞行,呱呱叫;旱鸭会低空飞行,呱呱叫;玩具鸭不会飞,会吱吱叫。
那这又该如何实现呢?
这个时候,再通过继承来实现不不太现实了。需要把飞行和叫这两种行为抽象出来,作为单独的行为类去实现,再给不同的鸭子分配不同的行为。
这就是策略模式。说白了,就是组合。
定义
策略模式 定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计原则
《Head First 设计模式》中提到几个设计原则:
- 找出引用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程。
- 多用组合,少用继承。
在面向对象的思想中,继承用的非常多,导致很多人习惯性的使用继承来解决问题,忽略了组合。
下次如果在使用继承解决类似问题时,请停下来思考思考,使用策略模式(组合)来解决是否更适合?