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();
}
}