我们先从一个经典的例子说起,假如现在我应聘去一家公司上班,第一天老板让我设计一个鸭子的类,
public abstract class Duck { public void quack(){ //叫唤 System.out.println("gua..."); } public void swim(){ //游泳 System.out.println("swimming..."); } public abstract void display();//外观 }
考虑到每个鸭子的外观都不同,所以把外观定为抽象类,
过了两天,老板决定给鸭子增加一个飞行的方法,that's so easy!,在Duck类里面加上就行了,
public abstract class Duck { public void quack(){ //叫唤 System.out.println("gua..."); } public void swim(){ //游泳 System.out.println("swimming..."); } public void fly() { //飞行 System.out.println("fly..."); } public abstract void display();//外观 }
但是这样做有个问题,有的鸭子不会飞,比如橡皮鸭之类的东东,如果继承这个类的话,也会飞起来,这该肿么办呢?
可以让不会飞的鸭子在继承Duck类时,覆盖fly()方法,例如:
public class RubberDuck extends Duck { @Override public void display() { System.out.println("I am a rubberDuck"); } @Override public void fly() { } }
有的鸭子即不会飞,也不会叫,也可以通过覆盖来完成,比如诱饵鸭
public class DecoyDuck extends Duck { @Override public void display() { System.out.println("I am a decoyDuck"); } @Override public void quack() { } @Override public void fly() { } }
但鸭子种类太多,方法也各不相同,每种鸭子都要写一些无用的代码来覆盖父类的方法,实在麻烦,所以我想到了接口,用接口就可以不用写那些无用的代码
//定义两个接口 public interface Flyable { public void fly(); } public interface Quackable { public void quack(); } //Duck类可以改写为 public abstract class Duck { public void swim(){ //游泳 System.out.println("swimming..."); } public abstract void display();//外观 } //橡皮鸭就可以不用写fly()这种无用的代码 public class RubberDuck extends Duck implements Quackable{ @Override public void display() { System.out.println("I am a rubberDuck"); } public void quack() { System.out.println("RubberDuck's quack..."); } }
这又产生一个问题,那就是代码无法像原来继承那样复用了,比如现在有100种各式各样的鸭子,其中50种鸭子的quack()方法一样,如果用上面的方法,就要写50次一模一样的quack(),也是麻烦,这里涉及到了一条重要的规则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
现在我们分开“变化和不会变化的部分”,建立两组类(完全远离Duck类),一组是和“fly”相关的,一组和“quack”相关,每组类实现各自的动作
//定义两个接口 public interface Flyable { public void fly(); } public interface Quackable { public void quack(); } //Duck类可以改写为 public abstract class Duck { Flyable fly; Quackable quack; public void swim(){ //游泳 System.out.println("swimming..."); } public abstract void display();//外观 } public class FlyWithWings implements Flyable{ public void fly(){ //实现了所有有翅膀的鸭子飞行行为。 } } public class FlyNoWay implements Flyable{ public void fly(){ //什么都不做,不会飞 } } public class Quack implements Quackable{ public void quack(){ //实现呱呱叫的鸭子 } } public class Squeak implements Quackable{ public void quack(){ //实现吱吱叫的鸭子 } } public class MuteQuack implements Quackable{ public void quack(){ //什么都不做,不会叫 } } //橡皮鸭 public class RubberDuck extends Duck { public RubberDuck() { quack = new MuteQuack(); fly = new FlyNoWay(); } @Override public void display() { System.out.println("I am a rubberDuck"); } }
这样做就比较容易扩展了,