设计模式之策略模式

实现鸭子的行为

在此,我们有两个接口,FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体的行为:
image.png
这 样 的 设 计 , 可 以 让 飞 行 和 呱 呱 叫 的 动 作 被 其 他的对象复用,因为这些行为已经与鸭子类无关了。而 我 们 可 以 新 增 一 些 行 为 , 不 会 影 响 到 既 有 的 行为类,也不会影响“使用”到飞行行为的鸭子类。 --这么一来,有了继承的“复用”好处,却没有继承所带来的包袱。

整合鸭子的行为

关键在于,鸭子现在会将飞行和呱呱叫的动作“委托”(delegate)别人处理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。
做法是这样的:
⑴ 首先,在Duck类中“加入两个实例变量” ,分别为“flyBehavior”与“quack Behavior”,声明为接口类型(而不是具体类实现类型),每个鸭子对象都会动态地设置这些变量以在运行时引用正确的行为类型(例如:FlyWithWings、Squeak等)。
我们也必须将Duck类与其所有子类中的fly()与quack()删除,因为这些行为已经被
搬到FlyBehavior与QuackBehavior类中了。
我们用两个相似的方法performFly()和performQuack()取代Duck类中的fly()与quack()。稍后你就会知道为什么。
image.png
⑵ 现在,我们来实现performQuack():
image.png
⑶ 好吧!现在来关心“如何设定flyBehavior与quackBehavior的实例变量”。
看看MallardDuck类: image.png

测试Duck的代码

  1. 输入并编译 下面的 D u c k类 ( D u c k . j a v a )以及两页前的MallardDuck类(MallardDuck.java)。
public abstract class Duck {
    //为行为接口类型声明两个引用变量,所有鸭子子类(在同一个package中)都继承它们。
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    /**
     * 展示
     */
    public abstract void display();

    public void performFly() {
        flyBehavior.fly();  // 委托给行为类
    }

    public void performQuack() {
        quackBehavior.quack();  // 委托给行为类
    }

    public void swim() {
        System.out.println("All duck float, even decoys!");
    }

    public void setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb;
    }

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

  1. 输入并编译FlyBehavior接口(FlyBehavior.java)与两个行为实现类(FlyWithWings.java与FlyNoWay.java)。
    image.png

  2. 输入并编译QuackBehavior接口(QuackBehavior.java)及其三个实现类(Quack.java、MuteQuack.java、Squeak.java) 。

public interface QuackBehavior {
    void quack();
}
----------------------------------------------------
public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}
----------------------------------------------------
public class MuteQuack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("<< Silence >>");
    }
}
----------------------------------------------------
public class Squeak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Squeak");
    }
}
  1. 输入并编译测试类(MiniDuckSimulator.java)
    image.png

总结

image.png

设计原则:封装变化;多用组合、少用继承;针对接口编程(针对接口编程”真正的意思是“针对超类型(supertype)编程”),不针对实现编程
定义:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户

posted @ 2021-12-22 20:16  追梦少年阿飞  阅读(70)  评论(0)    收藏  举报