第一次设计
所有鸭子都有共性,比如绿头鸭 红头鸭子,等等。所以我们建了一个超类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(); } }
我是模型鸭子
我有火箭助推器!
策略模式: 定义算法族,分别封装起来,让它们直接可以动态替换,让算法的变化独立于使用算法的客户。
借助了多态。