设计模式是被前人发现、经过总结形成了一套某一类问题的一般性解决方案。使用模式最好的方式是:把模式装进脑子,然后在设计和已有的应用中,寻找何处可以使用它们。以往是代码复用,现在是经验复用。

从模拟鸭子游戏说起

初始需求:各种鸭子(野鸭MallardDuck、红头鸭RedheadDuck等),一边游泳swim,一边呱呱叫quack,每种鸭子外观都不同display。

初始方案:设计一个鸭子超类,并让各种鸭子继承此超类。

设计模式入门——Head First

需求变更:让鸭子能够飞fly。

方案1:在Duck类中加上fly()。

结果:所有鸭子都继承fly,但并非所有鸭子都会飞,比如橡皮鸭RubberDuck(继承牵一发动全身)。

方案1_1:对于不能飞的鸭子,在子类中覆盖fly()。

结果:每当有新的鸭子出现,就要被迫检查并可能需要覆盖fly()。同理,对于叫声quack也一样。

方案2:把fly()和quack()从超类中取出,放进Flyable和Quackable接口中,只会飞的鸭子实现Flyable,会叫的实现Quackable。

 设计模式入门——Head First

结果:不会再有会飞的橡皮鸭,但由于接口不具有实现代码,造成代码无法复用(接口无法达到代码复用)。

方案2_1:设计两个接口FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体行为。

设计模式入门——Head First

结果:飞行和呱呱叫动作可以被其他的对象复用,因为这些行为已经与鸭子类无关;可以新增一些行为,不会影响到既有的行为类,也不会影响使用飞行行为的鸭子类(有了继承的复用好处,没了继承所带来的包袱)。

完善方案2_1:在Duck类中加入两个变量“flyBehavior”和“quackBehavior”,声明为接口类型,用performFly和performQuack分别取代fly和quack;同时加入两个新方法setFlyBehavior和setQuackBehavior,用来随时改变鸭子的行为。

设计模式入门——Head First

测试Duck的代码

Duck类(Duck.java)

public abstract class Duck {
    //所有鸭子子类都继承它
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public Duck(){
    }
    public abstract void display();
    
    public void perfmormFly(){
        //委托给行为类
        flyBehavior.fly();
    }
    public void performQuack(){
        //委托给行为类
        quackBehavior.quack();
    }
    public void setFlyBehavior(FlyBehavior fb){
        flyBehavior=fb;
    }
    public void setQuackBehavior(QuackBehavior cb){
        quackBehavior=cb;
    }
    public void swim(){
        System.out.println("All ducks float,even decoys!!");
    }
}
View Code

相关文章: