Head First设计模式读书笔记之策略模式

来源:互联网 发布:java包的命名规范 编辑:程序博客网 时间:2024/05/23 18:32
问题引入
A公司设计了一套鸭子游戏,游戏里会出现各种鸭子游泳,呱呱叫,因此系统那边设计了标准的OO技术,设计了一个超类Duck,所有不同的鸭子继承这个超类,Duck有三个方法:quack(), swim(), display(),因为每个不同种类的鸭子外观有所区别,display方法是抽象的,由具体实现类实现。后来老板新加了一个需求,需要一些鸭子能飞,于是就在超类Duck中加入fly()方法,导致所有的鸭子都会飞,i但是有些特殊的鸭子没有飞的技能,比如橡皮鸭子,有些鸭子不会飞也不会叫,比如诱饵鸭。继承的设计导致后期需求变动维护性越来越差。
解决方案1:
把fly()方法放入Flyable接口,只有会飞的鸭子才实现这个接口,同样的方式,设计一个Quackable接口,只有会叫的鸭子实现这个接口,这个方案看似能解决问题,但是改动量太大,所有继承Duck的类都需要修改,而且造成代码无法复用,这意味着无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中修改它,一不小心就可能造成新的错误。
解决方案2:
面向对象设计中有个设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些需要变化的代码混在一起。通过之前问题的描述我们知道经常变化的鸭子的fly()和quack()两个行为,根据这个原则,我们需要把这两个行为独立出来,建立一组新的类来代表每个行为。如何让鸭子的行为动态的改变?这里引出第二个设计原则:针对接口编程,而不是实现编程。我们利用接口代表每个行为,比如说,FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中的一个接口。类图如下:

这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用因为这些行为已经与鸭子类无关,而我们新增一些行为不会影响到既有的行为类,也不会影响使用到飞行行为的鸭子类。
Duck.java
public abstract class Duck {    FlyBehavior flyBehavior;    QuackBehavior quackBehavior;    public abstract void display();    public void performFly() {        flyBehavior.fly();    }    public void performQuack() {        quackBehavior.quack();    }    public void swim() {        System.out.println("all duck swim");    }}
FlyBehaivor.java
public interface FlyBehavior {    void fly();}
FlyWithWings.java
public class FlyWithWings implements FlyBehavior {    @Override    public void fly() {        System.out.print("I'm flying");    }}
FlyNoWay.java
public class FlyNoWay implements FlyBehavior{    @Override    public void fly() {       System.out.println("I can't fly");    }}
QuackBehavior.java
public interface QuackBehavior {    void quack();}
Quack.java
public class Quack implements QuackBehavior{    @Override    public void quack() {        System.out.println("Quack");    }}
Squeak.java
public class Squeak implements QuackBehavior {    @Override    public void quack() {        System.out.println("Squeak");    }}
MuteQuack.java
public class MuteQuack implements QuackBehavior {    @Override    public void quack() {        System.out.print("Silence");    }}
现在Duck类都有一个FlyBehavior和QuackBehavior,好将飞行和呱呱叫委托给它们代为处理,当将两个类结合起来使用,这就是组合。这种做法和继承不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象组合来的,这就是我们用到的第三个设计原则:多用组合,少用继承。使用组合建立系统具有很大的弹性,不仅可以将算法族封装成类,更可以在运行时动态改变行为,只要组合的行为对象符合正确的接口标准即可。

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

阅读全文
0 0