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


public class Strategy {

     public static void main(String[] args) {
  Duck mallardDuck = new MallardDuck();
  mallardDuck.display();
  mallardDuck.swim();
  mallardDuck.setFlyBehavior( new FlyWithWings());
  mallardDuck.setQuackBehavior( new Quack());
  mallardDuck.performFly();
  mallardDuck.performQuack();

  Duck rubberDuck = new RubberDuck();
  rubberDuck.display();
  rubberDuck.swim();
  rubberDuck.setFlyBehavior( new FlyNoWay());
  rubberDuck.setQuackBehavior( new Squack());
  rubberDuck.performFly();
  rubberDuck.performQuack();

    }
}

// 将变化的行为分离出来
interface FlyBehavior {
     void fly();
}

interface QuackBehavior {
     void quack();
}

// 不变的行为保留在Duck类中
abstract class Duck {
     // 保存两个变化动作类的实例
     private FlyBehavior flyBehavior;
     private QuackBehavior quackBehavior;

     public Duck() {
  flyBehavior = new FlyNoWay();
  quackBehavior = new Quack();
    }

     public abstract void swim();

     public abstract void display();

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

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

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

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

// FlyBehavior的实现
class FlyWithWings implements FlyBehavior {
     public void fly() {
  System.out.println( "fly");
    }
}

class FlyNoWay implements FlyBehavior {
     public void fly() {
  System.out.println( "I cant fly");
    }
}

// QuackBehavior的实现
class Quack implements QuackBehavior {
     public void quack() {
  System.out.println( "duck quack");
    }
}

class Squack implements QuackBehavior {
     public void quack() {
  System.out.println( "rubber duck quack");
    }
}

class MuteQuack implements QuackBehavior {
     public void quack() {
  System.out.println( "I cant quack");
    }
}

// 各种继承Duck类的具体类
class MallardDuck extends Duck {
     public void swim() {
  System.out.println( "swim");
    }

     public void display() {
  System.out.println( "I am a MallardDuck");
    }
}

class RedheadDuck extends Duck {
     public void swim() {
  System.out.println( "swim");
    }

     public void display() {
  System.out.println( "I am a RedheadDuck");
    }
}

class RubberDuck extends Duck {
     public void swim() {
  System.out.println( "swim");
    }

     public void display() {
  System.out.println( "I am a RubberDuck");
    }
}

class DecoyDuck extends Duck {
     public void swim() {
  System.out.println( "swim");
    }

     public void display() {
  System.out.println( "I am a DecoyDuck");
    }
}