oopstorm / oopstorm.github.io

https://oopstorm.github.io/
0 stars 15 forks source link

Head First Design Patterns · OopStorm #9

Open AlphaHinex opened 6 years ago

AlphaHinex commented 6 years ago

https://oopstorm.github.io/2018/04/05/2018-04-05-head-first-design-patterns/

jyoyou commented 6 years ago

Head First Design Patterns是一本通俗易懂的关于java设计模式的书籍。 借助一些有趣生动的例子,引出了不同的设计模式,更重要的是引导读者思考为何要使用当前的设计模式。 下面为大家介绍第一种设计模式:策略模式 策略模式的定义:策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 本章以一套鸭子设计为例: 鸭子类含有游泳、呱呱叫等方法。各种鸭子继承自鸭子父类。 当我想扩展一个飞行的行为给鸭子类。应该如何设计呢? 可能我们第一个想到的,就是在鸭子父类中加一个fly()方法。这样所有的子类就都拥有了fly()方法了。 那么这样做怎么样呢? 书中举了一个反例:橡皮鸭子能飞了。 有的朋友会说,那我将橡皮鸭子子类的fly方法override一下就可以了。 这样也会有问题,就如书中举例一样,希望每六个月就要更新产品(可能有更多的鸭子子类)。从维护的角度考虑,每次更新子类,那么都要检查一遍是否有必要将fly方法覆盖掉。想想就恐怖。 开来继承并不是一个好主意。

那么应该如何设计呢?我们可能接着会想到接口。如果将fly方法从超类中抽离出来,封装为接口,那么只有拥有飞行行为的鸭子子类才实现该接口。这样一来,就可以实现子类有选择的实现行为接口并实现该fly方法了。 看上去似乎问题解决了。 不过我们再来看下这样设计之后,会遇到的问题: 由于接口没有实现代码。那么我们必须在所有实现了fly接口的鸭子子类中大量的重复编写fly方法。这样显然是不好的。代码的复用率被大大降低。同时在后续的维护工作中,如果需要修改fly方法,那么你需要将所有实现了fly接口的子类全部修改一遍。很恐怖。

那么如何优化改善呢? 书中给出了一些理念,或者说设计原则: 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。这个概念很简单,几乎是每个设计模式背后的精神所在,所有的模式都提供了一套方法让系统中的某部分改变不会影响其它部分。

分开变化和不变化的部分

为了要分开变化和不变化的部分,我们准备建立两组类,一个是fly相关,一个是quack相关的,每一组类将实现各自的动作。比如说,我们可能有一个类实现“呱呱叫”,另一个类实现“叽叽叫”,另一个类实现“安静”。

将鸭子的行为设计成接口,并创建行为的实现类(而不是直接使用鸭子子类来实现接口方法),我们可以称其为行为类。

这里就引申出了另一个设计原则:面向接口编程,而不是面向实现编程。

经过改良后,我们使用接口来定义鸭子的飞行、呱呱叫行为,同时这些行为有自己的实现类,而不是鸭子子类。 我们将这些行为以接口的形式定义在鸭子超类当中。 这样一来,我们实现了代码的复用(当调用飞行方法时,使用的是飞行接口自己的行为实现类,所有的鸭子类都调用同一套行为实现类)。 在维护时,我们只修改行为实现类就可以了。 同时,在不同的鸭子子类当中,对于飞行、呱呱叫等行为,由于设计了多种行为类来实现接口(比如会飞、不会飞、飞的高、飞的低;会叫、不会叫、嘎嘎叫、呱呱叫),所以在实例化时,可以灵活选择符合自己的行为实现类,来实现父类的行为接口。

以上就是参考 Head First Design Patterns,对策略模式的一些总结