第一次设计


所有鸭子都有共性,比如绿头鸭 红头鸭子,等等。所以我们建了一个超类Duck,即抽象类
因为每种鸭子叫的方式或者外观不一样,所以超类定义了三个抽象的方法, 叫、游泳、外观。


定义抽象类

  1. public abstract class Duck {
  2. abstract void quack();
  3. abstract void swim();
  4. abstract void display();
  5. }

俩只鸭子子类

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


  1. public class RedheadDuck extends Duck {
  2. @Override
  3. void quack() {
  4. }
  5. @Override
  6. void swim() {
  7. }
  8. @Override
  9. void display() {
  10. System.out.println("我是红色的");
  11. }
  12. }
  1. public class RubberDuck extends Duck {
  2. @Override
  3. void quack() {
  4. }
  5. @Override
  6. void swim() {
  7. }
  8. @Override
  9. void display() {
  10. System.out.println("外观是橡皮");
  11. }
  12. }

新需求:鸭子能飞
现在要鸭子能飞。
那么很好,我们只需这样,在超类上加一个fly行为不就行了?


  1. public abstract class Duck {
  2. abstract void quack();
  3. abstract void swim();
  4. abstract void display();
  5. abstract void fly();
  6. }

暴露问题


那么问题来了,橡皮鸭子可不会飞啊,如果再加一个木头鸭呢?它可不会叫啊。
会发现,不同的鸭子我甚至根本不需要某些方法, 那么子类却要被强制实现该方法,尽管我可以不重写。
也就是说,我现在想要单独给某个鸭子加上个fly()!, 不影响其它已经存在的鸭子。

提出假象


既然如此,不如将fiy() 做成一个接口,哪个鸭子能飞,我就让它实现一下不就行了?
不建议这么做的理由:
1、假如鸭子有上千个行为,你是否要定义上千个接口呢?
2、违背初衷,目前超类的存在,它的代码复用价值已经不大了。

解决方案


从解决方案一中可以发现思路,既然抽出一个行为(比如fly)不行,那么干脆把鸭子的所有行为都抽象出来吧。
因为鸭子的行为一直是在变动的。为了不影响稳定的行为,那么干脆让它们分离开。

抽离出fly行为


  1. public interface FlyBehavior {
  2. void fly();
  3. }

抽离出quack行为


  1. public interface QuackBehavior {
  2. void quack();
  3. }

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


  1. public class FlyWithWings implements FlyBehavior {
  2. @Override
  3. public void fly() {
  4. System.out.println("我带着翅膀飞!");
  5. }
  6. }

  1. public class FlyNoWay implements FlyBehavior {
  2. @Override
  3. public void fly() {
  4. System.out.println("我不会飞!");
  5. }
  6. }

这个时候你会发现,凡是会飞的鸭子那么我就拿走 FlyWithWings这个类好了。
即使我在加几个飞的动作,也不会影响到已经存在的鸭子行为。

第二次设计


  1. public abstract class Duck {
  2. FlyBehavior flyBehavior;
  3. QuackBehavior quackBehavior;
  4. public abstract void display();
  5. public void performFly(){
  6. flyBehavior.fly();
  7. }
  8. public void performQuack(){
  9. quackBehavior.quack();
  10. }
  11. public void setFlyBehavior(FlyBehavior flyBehavior) {
  12. this.flyBehavior = flyBehavior;
  13. }public void setQuackBehavior(QuackBehavior quackBehavior) {
  14. this.quackBehavior = quackBehavior;
  15. }
  16. }

红头鸭


  1. public class RedheadDuck extends Duck{
  2. @Override
  3. public void display() {
  4. System.out.println("我是红头鸭");
  5. }
  6. }

橡皮鸭


  1. public class RubberDuck extends Duck{
  2. @Override
  3. public void display() {
  4. System.out.println("我是橡皮鸭");
  5. }
  6. }

测试

红头鸭


  1. public class Test {
  2. public static void main(String[] args) {
  3. Duck redHeadDuck = new RedheadDuck();
  4. redHeadDuck.display()
  5. redHeadDuck.setFlyBehavior(new FlyWithWings());      //给它一个fly行为 的实现类
  6. redHeadDuck.performFly();
  7. }
  8. }
  9. 我是红头鸭
  10. 我带着翅膀飞!

橡皮鸭


  1. public class Test {
  2. public static void main(String[] args) {
  3. Duck rubberDuck = new RubberDuck();
  4. rubberDuck.display();
  5. rubberDuck.setFlyBehavior(new FlyNoWay());   //给它一个fly行为 的实现类
  6. rubberDuck.performFly();
  7. }
  8. }
  9. 我是橡皮鸭
  10. 我不会飞!

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

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


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

  1. public class FlyRocketPowered implements FlyBehavior {
  2. @Override
  3. public void fly() {
  4. System.out.println("我有火箭助推器!");
  5. }
  6. }

测试


  1. public class Test {
  2. public static void main(String[] args) {
  3. ModelDuck modelDuck = new ModelDuck();
  4. modelDuck.display();
  5. modelDuck.setFlyBehavior(new FlyRocketPowered());
  6. modelDuck.performFly();
  7. }
  8. }
  9. 我是模型鸭子
  10. 我有火箭助推器!

小节:下定义


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