策略模式-鸭子应用:Head first

 

第一次设计

 

所有鸭子都有共性,比如绿头鸭 红头鸭子,等等。所以我们建了一个超类Duck,即抽象类

 因为每种鸭子叫的方式或者外观不一样,所以超类定义了三个抽象的方法, 叫、游泳、外观。

public abstract class Duck {

    abstract void quack();

    abstract void swim();

    abstract void display();

}

俩只鸭子,一只红头鸭子,一只橡皮鸭子。

public class RedheadDuck extends Duck {
    @Override
    void quack() {

    }

    @Override
    void swim() {

    }

    @Override
    void display() {
        System.out.println("我是红色的");
    }
}
public class RubberDuck extends Duck {
    @Override
    void quack() {

    }

    @Override
    void swim() {

    }

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

 

新需求

现在要鸭子能飞。

那么很好,我们只需这样,在超类上加一个fly行为不就行了?

public abstract class Duck {

    abstract void quack();

    abstract void swim();

    abstract void display();

    abstract void fly();
}

 

问题一

那么问题来了,橡皮鸭子可不会飞啊,如果再加一个木头鸭呢?它可不会叫啊。

会发现,不同的鸭子我甚至根本不需要某些方法, 那么子类却要被强制实现该方法,尽管我可以不重写。

 

也就是说,我现在想要单独给某个鸭子加上个fly()!, 不影响其它已经存在的鸭子。

 

解决方案一

 

既然如此,不如将fiy() 做成一个接口,哪个鸭子能飞,我就让它实现一下不就行了?

不建议这么做的理由:

1、假如鸭子有上千个行为,你是否要定义上千个接口呢?

2、违背初衷,超类的存在,它的代码复用价值已经不大了。

 

 

解决方案二

从解决方案一中可以发现思路,既然抽出一个行为(比如fly)不行,那么干脆把鸭子的所有行为都抽象出来吧。

因为鸭子的行为一直是在变动的。为了不影响稳定的行为,那么干脆让它们分离开。

 

抽离出fly行为

public interface FlyBehavior {

    void fly();
}

 

抽离出quack行为

public interface QuackBehavior {

    void quack();
}

 

我让所有飞的行为,不论是挥着翅膀飞还是滑行着飞,还是不会飞,我都必须实现这个FlyBehavior这个接口

public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我带着翅膀飞!");
    }
}
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我不会飞!");
    }
}

 

这个时候你会发现,凡是会飞的鸭子那么我就拿走 FlyWithWings这个类好了。

即使我在加几个飞的动作,也不会影响到已经存在的鸭子行为。

 

第二次设计

public abstract class Duck {

    FlyBehavior flyBehavior;

    QuackBehavior quackBehavior;

    public abstract void display();

  public void performFly(){
        flyBehavior.fly();
    }
    public void performQuack(){
        quackBehavior.quack();
    }

public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

 

红头鸭

public class RedheadDuck extends Duck{

    @Override
    public void display() {
        System.out.println("我是红头鸭");
    }

  
}

橡皮鸭

public class RubberDuck extends Duck{

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

  
}

 

测试一下

红头鸭

public class Test {

    public static void main(String[] args) {

        Duck redHeadDuck = new RedheadDuck();
        redHeadDuck.display()
        redHeadDuck.setFlyBehavior(new FlyWithWings());      //给它一个fly行为 的实现类
        redHeadDuck.performFly();
        
    }
}

我是红头鸭
我带着翅膀飞!

橡皮鸭

public class Test {

    public static void main(String[] args) {

        Duck rubberDuck = new RubberDuck();

        rubberDuck.display();
    
        rubberDuck.setFlyBehavior(new FlyNoWay());   //给它一个fly行为 的实现类

        rubberDuck.performFly();
    }
}
我是橡皮鸭

我不会飞!

 

 

新增需求,再添加一个模型鸭子

 

我要求这个鸭子能飞,但是它没有翅膀。 很简单,再实现一次飞行的行为即可

 

public class ModelDuck extends Duck {
    
    @Override
    public void display() {
        System.out.println("我是模型鸭子");
    }


}
public class FlyRocketPowered implements FlyBehavior {


    @Override
    public void fly() {
        System.out.println("我有火箭助推器!");
    }
}

测试

public class Test {

    public static void main(String[] args) {

        ModelDuck modelDuck = new ModelDuck();

        modelDuck.display();
        modelDuck.setFlyBehavior(new FlyRocketPowered());

        modelDuck.performFly();
    }
}
我是模型鸭子
我有火箭助推器!

 

 

 

 

策略模式: 定义算法族,分别封装起来,让它们直接可以动态替换,让算法的变化独立于使用算法的客户。

 

借助了多态。

 

上一篇:DotNetZip生成多个excel文件损坏-踩坑填坑系列


下一篇:数组:Demo6_ArrayDouble