1.设计案例:
设计一个对象(鸭子),该鸭子会游泳、叫、吃东西、跳跃、颜色等等属性
一般设计方式:
定义超类(super class),该类中定义共同属性
编写各种子类,均继承该super class,定义其特殊属性
需求变更一:新增鸭子功能,让鸭子会飞
修改方式:在super class中定义飞的属性,并提供实现
问题:并不是所有的鸭子都需要飞,比如木头鸭子;牵一发而动全身
需求变更一新设计:添加fly interface
实现结果:让能飞行的鸭子实现该interface
问题:代码无限重复(因为继承该interface的子类均需要实现该方法)
好吧,我们暂时先这样做,虽然麻烦,但是他可以运行
需求变更二:让鸭子实现不同的飞行模式
实现结果:修改继承该interface的所有实现类
问题:鬼知道你是不是少了那个子类的实现
好吧,虽然麻烦,但起码实现了不是,那么这样的设计结果如下:
public class Duck{ public void eat(){} public void display(){} } public interface fly{ void fly(); } public class RedDuck extends Duck implements fly{ ... } public class GreenDuck extends Duck implements fly{ ... } public class WoodDuck extends Duck{ ... }
问题:随着需求的更迭,代码会进一步复杂,维护麻烦,且代码不能重用,修改时很容易漏掉。
综上:这种设计模式在变更频繁的需求中是不可取的。
更好的解决方案:针对接口编程,抽取容易变更的部分,进行封装,实现代码复用,系统弹性。
代码如下:
public class Duck{ //定义接口属性,利用多态,动态调用不同的实现 Fly fly; Call call; //提供get set方法,目的是以后可以通过set动态随时变换其实现 ....get/set //提供动态调用不同实现的方法 public void performFly(){ fly.fly(); } public void performCall(){ call.call(); } public void eat(){} public void display(){} } //将经常变化的属性抽取成接口,通过实现这些接口完成不通的变化 public interface Fly{ public void fly(); } public interface Call{ public void call(); } public class FlyWithWings implements fly{ public void fly(){ System.out.println("can fly"); } } public class FlayNoWay implements fly{ public void fly(){}//不会飞,这里什么都不做 } public class call1 implements call{ public void call(){ System.out.println("call 111"); } } public class call2 implements call{ public void call(){ System.out.println("call 222"); } } //动态调用方式 public class RedDuck extends Duck{ //通过构造方法来定义动态调用的实现类 public RedDuck(){ fly = new FlyWithWings(); call = new Call1(); } }