举个例子:现在要设计一个程序模拟各种鸭子,包括玩具鸭和真鸭子。
每个鸭子都具有呱呱叫 quack() 和 飞行 fly() 方法。
我们首先想到的设计方法是 定义一个超类duck,超类实现fly()、quack()方法。然后定义各种鸭子子类去继承超类duck。
但是这样导致的问题是有的鸭子只会quack或fly,而且叫声和飞行方式也分很多种,如果继承两个方法每次都要重写显然不方便,会增加代码长度。
所以,引出设计原则一:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的混合在一起。 设计原则二:针对接口编程,而不是针对实现编程写程序时应该尽可能增加代码的弹性,如果如例子中那样设计,一旦鸭子需要增加新技能,我们都必须到原来的代码中去修改,这种属于静态定义行为,即在代码编写时就决定了对象的行为,这不是我们想要的好的设计。
我们需要的是在程序运行时能够动态改变行为。
设计原则三:多用组合,少用继承
于是,我们把fly和quack单独拿出来定义成接口FlyBehavior和QuackBehavior。
1 public interface FlyBehavior { 2 public void fly(); 3 }
1 public interface QuackBehavior { 2 public void quack(); 3 }
接着在定义quack类和fly类实现接口
public class MuteQuack implements QuackBehavior{ @Override public void quack() { System.out.println("<< Silence >>"); } } public class Quack implements QuackBehavior{ @Override public void quack() { System.out.println("quack!"); } } public class Squeak implements QuackBehavior{ @Override public void quack() { System.out.println("squeak!"); } }
public class FlyNoWay implements FlyBehavior{ @Override public void fly() { System.out.println("i can not fly!"); } } public class FlyWithWings implements FlyBehavior{ @Override public void fly() { System.out.println("i am flying!"); } }
然后再定义超类Duck
1 public abstract class Duck { 2 public FlyBehavior flybehavior; 3 public QuackBehavior quackbehavior; 4 5 public abstract void display(); 6 7 public void performFly(){ 8 flybehavior.fly(); 9 } 10 11 public void performQuack(){ 12 quackbehavior.quack(); 13 } 14 15 public void swim(){ 16 System.out.println("all ducks can swim!"); 17 } 18 19 public void setFlyBehavior(FlyBehavior fb){ 20 flybehavior = fb; 21 } 22 23 public void setQuackBehavior(QuackBehavior qb){ 24 quackbehavior = qb; 25 } 26 }
在超类中实例化引用两个行为接口
接着定义鸭子具体类继承自超类Duck
1 public class MallardDuck extends Duck{ 2 public MallardDuck() { 3 flybehavior = new FlyWithWings(); 4 quackbehavior = new Quack(); 5 } 6 @Override 7 public void display() { 8 // TODO Auto-generated method stub 9 System.out.println("i am a mallardDuck!"); 10 } 11 }
在具体类构造方法中我们将超类的行为引用定义为new FlyWithWings(),new Quack()
实现类
public class test { public static void main(String[] args) { Duck d = new MallardDuck(); d.performFly(); d.performQuack(); d.display(); } }
这样就可以动态的修改鸭子的行为,用setFlyBehavior(FlyBehavior fb)和setQuackBehavior(QuackBehavior qb).