0%

策略模式(Strategy Pattern)

在大学的时候,看过一本设计模式的书。那时是上网找的pdf,书名不记得了。但是印象最深刻的是,那本书特别晦涩难懂,翻译的特别拗口。虽然硬着头皮看完了,但是记住的没有多少。

如今,买了一本《Head First 设计模式》,开始重新学习设计模式。边学边记录,算是学习笔记吧。这篇是《Head First 设计模式》学习笔记第一篇:策略模式。
(好吧,我又开了一个坑,能不能坚持写完还另说。)

从问题入手

《Head First 设计模式》书中提到的Duck的例子非常的形象,我用自己的画重新表述一遍,跟书中略有区别。

  1. 需要实现一个鸭子Duck类,鸭子有一种行为:飞行
  2. 正常的鸭子会飞,但是玩具鸭不会飞。

我们很自然的想到,实现基类Duck类,提供一个默认的fly方法,玩具鸭重写fly方法,提供一个空实现。

或者是基类不提供fly方法实现,实现两个子类FlyableDuckToyDuck,其中FlyableDuck表示会飞的鸭子,实现fly方法;ToyDuck表示玩具鸭,提供空的fly方法。

就我列出的两点的要求来说,两个方法都可以实现。但有以下缺点:

  • 方法一:如果后续新增加一种不会飞的鸭子时,需要关心父类已经实现了对应的fly方法,需要主动覆盖fly方法
  • 方法二:如果后续新增一种叫的行为,分为吱吱叫、呱呱叫,飞行行为也分为蜻蜓点水飞行、低空飞行两种,那是不是就得实现四个类表示行为两两组合的鸭子呢?

那么接下来,再提几个要求:

  1. 鸭子分为普通鸭,池塘鸭,旱鸭,玩具鸭
  2. 普通鸭会低空飞行,吱吱叫,池塘鸭会蜻蜓点水飞行,呱呱叫;旱鸭会低空飞行,呱呱叫;玩具鸭不会飞,会吱吱叫。

那这又该如何实现呢?

这个时候,再通过继承来实现不不太现实了。需要把飞行和叫这两种行为抽象出来,作为单独的行为类去实现,再给不同的鸭子分配不同的行为。

Duck

这就是策略模式。说白了,就是组合。

定义

策略模式 定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

设计原则

《Head First 设计模式》中提到几个设计原则:

  1. 找出引用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
  3. 多用组合,少用继承。

在面向对象的思想中,继承用的非常多,导致很多人习惯性的使用继承来解决问题,忽略了组合。
下次如果在使用继承解决类似问题时,请停下来思考思考,使用策略模式(组合)来解决是否更适合?