《Head First 设计模式》笔记1

前言

对白很有趣,而且营造地很有氛围,如果还不会设计模式的话是值得一读的。

本笔记当然不会有那些有趣的图片和氛围,内容也会尽量浓缩。

策略模式(Strategy)

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

栗子

某公司做了一款鸭子游戏,游戏中的鸭子可以游泳,可以呱呱叫。系统设计了一个鸭子抽象类,让各种鸭子都继承它:

abstract class Duck {
    void quack() {
        System.out.println("呱呱叫");
    }

    void swim() {
        System.out.println("游泳");
    }

    abstract void display();
}

其中一些鸭子:

class MallardDuck extends Duck {
    @Override
    void display() {
        System.out.println("绿头鸭子");
    }
}

class RedheadDuck extends Duck {
    @Override
    void display() {
        System.out.println("红头鸭子");
    }
}

提需求

现在公司要游戏中的鸭子能飞。

最简单的方案:给鸭子抽象类加上 fly 方法,这样鸭子们都能飞了。

void fly() {
    System.out.println("飞");
}

对于真鸭子来说,该方法没有多大问题。但对于假鸭子来说,该方法就不对了,比如橡皮鸭,根本就不能飞,而且另一个 quack 方法也不适用于橡皮鸭,因为它是吱吱叫的。

当然,对于橡皮鸭,你可以覆盖 quack 方法和 fly 方法:

class RubberDuck extends Duck {
    @Override
    void quack() {
        System.out.println("吱吱叫");
    }

    @Override
    void display() {
        System.out.println("橡皮鸭");
    }

    @Override
    void fly() {
        // 什么都不做
    }
}

但如果现在又新添加了一只诱饵鸭呢?它是木头假鸭,既不会飞又不会叫,如果还是使用上面的方法的话就是:

class DecoyDuck extends Duck {
    @Override
    void quack() {
        // 什么都不做
    }

    @Override
    void display() {
        System.out.println("诱饵鸭");
    }

    @Override
    void fly() {
        // 什么都不做
    }
}

给程序员很明显的感觉就是,我都不需要这些什么都不做的行为,多么冗余的代码,但不覆盖又不行,不然这些鸭子的行为就不对了。所以利用继承来提供鸭子的行为导致了以下缺点:
- 代码在多个子类中重复。
- 运行时的行为不容易改变。
- 很难知道所有鸭子的全部行为。
- 改变会牵一发动全身,造成其他鸭子不想要的改变。

满足需求

设计原则一:找出应用中可能需要变化的地方,把它们独立出来,不要和那些不需要变化的代码混在一起。

既然鸭子的行为是变化的,那么根据原则一,我们要做的就是把鸭子的行为从鸭子抽象类 Duck 中抽出来,那抽出来后怎么定义具体鸭子的行为呢?那当然是定义具体鸭子的同时,定义其行为。

设计原则二:针对接口编程,而不是针对实现编程。
设计原则三:多用组合,少用继承。

根据原则二,写出对应的飞和叫这两种行为的接口:

飞的行为:

interface FlayBehavior {
    void fly();
}

具体飞的动作的两个实现:

class FlyWithWings implements FlayBehavior {
    @Override
    public void fly() {
        System.out.println("飞");
    }
}

class FlyNoWay implements FlayBehavior {
    @Override
    public void fly() {
        // 不会飞,什么都不做
    }
}

叫的行为:

interface QuackBehavior {
    void quack();
}

具体叫的动作的三个实现:

class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("呱呱叫");
    }
}

class Squeak implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("橡皮鸭吱吱叫");
    }
}

class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        // 不会叫,什么都不做
    }
}

给鸭子抽象类添加这些行为,并且加入 setter,让这些行为可以动态设置:

abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    // 如果想要改变鸭子的飞行
    void setFlyBehavior(FlyBehavior behavior) {
        this.flyBehavior = behavior;
    }

    void setQuackBehavior(QuackBehavior behavior) {
        this.quackBehavior = behavior;
    }

    void quack() {
        quackBehavior.quack();
    }

    void fly() {
        flyBehavior.fly();
    }

    void swim() {
        System.out.println("游泳");
    }

    abstract void display();
}

然后就可以在构造器里实现具体行为了:

class MallardDuck extends Duck {
    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    @Override
    void display() {
        System.out.println("绿头鸭子");
    }
}

class RubberDuck extends Duck {
    public RubberDuck() {
        quackBehavior = new Squeak();
        flyBehavior = new FlyNoWay();
    }

    @Override
    void display() {
        System.out.println("橡皮鸭子");
    }
}

测试

public class Main {
    public static void main(String[] args) throws IOException {
        RubberDuck rubberDuck = new RubberDuck();
        rubberDuck.display();
        rubberDuck.fly();
        rubberDuck.quack();
        // 橡皮鸭也变成呱呱叫
        QuackBehavior quack = new Quack();
        rubberDuck.setQuackBehavior(quack);
        rubberDuck.quack();
        System.out.println("--------");
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.display();
        mallardDuck.fly();
        mallardDuck.quack();
    }
}

输出:
橡皮鸭子
橡皮鸭吱吱叫
呱呱叫
——–
绿头鸭子

呱呱叫

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值