前景问题:

  1. 有时,想着只需要在基类中加上自己所需要的方法,所有子类就会继承该方法。但是对代码所做的局部修改,影响层面可能不是局部。你会体会到一件事:当涉及“维护”时,为了“复用”(reuse)目的而使用继承,结局并不完美。
  2. 这时,你会考虑:利用接口如何?把自己想要添加的方法从超类中取出来,放进一个“XXXable接口”中。这么一来,只有想要实现该方法的子类才实现该接口。这样如何?这真是个超笨的注意!你没有发现这么一来重复的代码会变多吗?这其实和使用继承时无止境的覆盖不需要该方法的子类一样差劲。

思考:

  1. 我们知道,有时并非所有的子类都有我们所需要添加的方法,所以继承不是适当的解决方式。虽然接口可以解决一部分问题,但是却造成代码无法复用,这只能算是从一个噩梦跳进另一个噩梦。
  2. 如果能有一种建立软件的方法,好让我们可以用一种对既有的代码影响最小的方式来修改软件该有多好。我们可以花较小的时间重做代码,而让程序去做更酷的事情。
  3. 软件开发的一个不变真理:不管你在何处工作,构建些什么,用何种编程语言,在软件开发上,一直伴随你的那个不变真理是什么?A:不管当初软件设计得多好,一段时间后,总有需要成长与改变,否则软件就会死亡。

解决方案:

  1. 幸运的是,有一个设计原则,恰好适用于此状况。A:找出应用中可能需要变化之处,把它们独立出来,不需要和那些不需要变化的代码混在一起。换句话说,如果每次新的需求一来,都会使某个方面的代码发生变化,那么你就可以确定,这部分代码需要被抽出来,和其他稳定的代码有所区分。也可以换一中思考方式:“把会变化的部分取出来并封装起来,以便以后可以轻易地改动或扩展此部分,而不影响不需要变化的其他部分”。这样的概念很简单,几乎是每个设计模式背后的精神所在。所有的模式都提供一套方法让“系统中的某部分改变不影响其他部分”。
  2. 于是我们不打算对基类做太多处理。而为需要添加的那些方法准备各自相关的类,每一组类将实现各自的动作。从现在开始,行为们将被放在分开的类中,这个类专门提供某些行为接口的实现。这些类我们称之为“行为”类由行为类而不是由子类来是实现行为接口。这样的做法迥异与以往,以前的做法:行为来自父类的具体实现,或是继承某个接口并由子类自行实现而来。这两种做法都是依赖于“实现”,没办法更改行为。以上这些所说的其实就是第二个设计原则:针对接口编程,而不是针对实现编程。

 


示例:假设要开发一个鸭子游戏,游戏中出现各种鸭子,一边游泳戏水,一边呱呱叫。

1.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. }  

 

2.FlyBehavior接口(FlyBehavior.java)

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

3.两个行为是实现类

(FlyWithWings.java) 

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

(FlyNoWay.java)

 
  
  1. public class FlyNoWay implements FlyBehavior{ 
  2.     public void fly(){ 
  3.         System.out.println("I can't fly"); 
  4.     } 

4.QuackBehavior接口(QuackBehavior.java)及三个实现类

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

(Quack.java)

 
  
  1. public class Quack implements QuackBehavior{ 
  2.     public void quack(){ 
  3.         System.out.println("Quack"); 
  4.     } 

(MuteQuack)

 
  
 
  
  1. public class MuteQuack implements QuackBehavior{ 
  2.     public void quack(){ 
  3.         System.out.println("<<Silence>>"); 
  4.     } 

(Squeak.java)

 
  
  1. public class Squeak implements QuackBehavior{ 
  2.     public void quack(){ 
  3.         System.out.println("Squeak"); 
  4.     } 

5.子类(MallardDuck)

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

6.输出并编译测试类(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.     } 

7.运行结果: