这篇博文是对前一篇博文《设计模式1:找出应用中可能需要变化之处,把它们独立出来》的一个延伸思考:在鸭子里建立了一堆动态的功能没有用到,太可惜了!假设我们想在鸭子子类中通过“设定方法(setter method)”来设定鸭子的行为,而不是在鸭子的构造器内实例化,那应该如何操作呢?

1.首先我们要在Duck类中加入两个新的方法:

Duck类(Duck.java)(粗体为新加入的两个方法)

 
  
  1. public abstract class Duck { 
  2.     FlyBehavior flyBehavior; 
  3.     QuackBehavior quackBehavior; 
  4.     public Duck(){ 
  5.     } 
  6.     public abstract void display(); 
  7.     public void performFly(){ 
  8.         flyBehavior.fly(); 
  9.     } 
  10.     public void performQuack(){ 
  11.         quackBehavior.quack(); 
  12.     } 
  13.     public void swim(){ 
  14.         System.out.println("All ducks float, even decoys!"); 
  15.     } 
  16.     public void setFlyBehavior(FlyBehavior fb){ 
  17.         flyBehavior=fb; 
  18.     } 
  19.     public void setQuackBehavior(QuackBehavior qb){ 
  20.         quackBehavior=qb; 
  21.     } 

2.模仿上一篇中的MallardDuck制作一个新的鸭子类型:模型鸭子(ModelDuck.java)

 
  
  1. public class ModelDuck extends Duck{ 
  2.     public ModelDuck(){ 
  3.         flyBehavior=new FlyNoWay(); 
  4.         quackBehavior=new Quack(); 
  5.     } 
  6.     public void display(){ 
  7.         System.out.println("I'm a model duck"); 
  8.     } 

3.同样模仿上一篇的FlyNoWay制作一个新的FlyBehavior类型(FlyRocketPowered.java)

 
  
  1. public class FlyRocketPowered implements FlyBehavior{ 
  2.     public void fly(){ 
  3.         System.out.println("I'm flying with a rocket!"); 
  4.     } 

4.接下来才开始比较令人兴奋的地方:改变测试类(MiniDuckSimulator.java),加入模型鸭子,并使模型鸭子具有火箭动力。

 
  
  1. public class MiniDuckSimulator {  
  2.     public static void main(String[] args){  
  3.         Duck mallard=new MallardDuck();  
  4.         mallard.performQuack();  
  5.         mallard.performFly();  
  6.         mallard.display();  
  7.         Duck model=new ModelDuck(); 
  8.         model.performFly(); 
  9.         model.setFlyBehavior(new FlyRocketPowered()); 
  10.         model.performFly(); 
  11.         model.display(); 
  12.     }  
  13. }  

5.测试结果