HeadFirst 设计模式阅读笔记(一)—— strategy

最近正是圣诞假期,利用空闲时间翻翻《HeadFirst 设计模式》。这本书编的很有意思,读起来并不枯燥。所有设计模式的示例代码可以在官方网站免费下载:http://wickedlysmart.com/get-code/,但是我觉得自己写写可能更好些。


本系列笔记的目的不是把原书抄一遍,而是只摘录一些笔者认为重要的知识点,供以后查阅。希望详细学习的朋友们不妨去看看原书,确实比一般的技术书轻松多了。


第一章主要介绍了“策略模式”,以鸭子类为例讲述了这样一个问题:

  1. 最初设计鸭子这个基类时,我们定义了“呱呱叫”方法,子类“绿头鸭”继承鸭子类,一切显得很完美。
  2. 现在系统升级,多了很多种鸭子,比如“模型鸭子”,它真心不会叫,怎么办?
  3. 最简单的方法是在“模型鸭子”类中重写“呱呱叫”使之为空。但是很明显每次有新的不会叫的鸭子出现时我们都要想着重写这个方法,这显然是一个“肮脏”的解决方案。
  4. 于是我们想到可以把这个行为抽象成一个接口,每个子类根据自己的需要,如果能叫就实现这个接口。听上去不错。
  5. 可是别忘了,大部分鸭子还是呱呱叫的!使用接口使得我们不得不重复相同的代码。
  6. 如何在继承和复用之间找到平衡?
这是一些经验:
  • 为了复用而使用继承效果往往不完美
  • 针对接口而不是针对实现编程
  • 找出应用中可能变化的行为,把他们独立出来(封装)。如此一来系统变得更有弹性。
  • 多用组合少用继承
最终解决方案:
  1. 把“叫”这一方法抽象成为一个接口。
  2. 不同的叫的方式,比如呱呱叫和吱吱叫被抽象为具体的类,他们实现“叫”接口。
  3. 在基类“鸭子中”如此定义:
      
package headfirst.strategy;
public abstract class Duck {
FlyBehavior flyBehavior;
public Duck() {}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
public void performQuack() {
quackBehavior.quack();
}
}
现在我们不再直接在类中实现“叫”方法(针对实现编程),而是定义了一个接口类型的属性来代表这一方法(针对接口编程),如此一来系统就变得灵活多了,因为子类的行为可以在运行时改变!
例:
ModelDuck.java,
public class ModelDuck extends Duck {
public ModelDuck() {
quackBehavior = new 呱呱叫();
}
main:
Duck model = new ModelDuck();
model.performQuack();//现在是呱呱叫
model.setQuackBehavior(new 吱吱叫());
model.performQuack();//现在是吱吱叫!


我们能够随时改变模型鸭子的叫声了。
这就是strategy模式:
定义一个算法族,分别封装起来让他们可以互相替换,此模式使算法的变化独立于使用算法的客户。
更直观的一个例子是,在射击游戏中,角色可以随时变化他们手中的枪!setWeapon()...

猜你喜欢

转载自blog.csdn.net/tangwing/article/details/8444843
今日推荐