模拟鸭子项目:
不使用设计模式的方案:
传统继承方式如下:
鸭子超类:
public abstract class Duck { public void Quack() { System.out.println("~~gaga~~"); } public abstract void display(); public void swim() { System.out.println("~~im swim~~"); } }
GreenHeadDuck继承Duck :
public class GreenHeadDuck extends Duck { @Override public void display() { System.out.println("**GreenHead**"); } }
同理可有RedHeadDuck等子类
应对新的需求,看看这个设计的可扩展性
1)添加会飞的鸭子
继承方式解决方案是:
public abstract class Duck { ...; public void Fly() { System.out.println("~~im fly~~"); } };
问题来了,这个Fly让所有子类都会飞了,这是不科学的。
继承的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应
继续使用继承方式解决方案是(覆盖父类方法):
public class GreenHeadDuck extends Duck { ...; public void Fly() { System.out.println("~~no fly~~"); } }
又有新需求,石头鸭子,填坑(每个子类都要覆盖父类的方法):
public class StoneDuck extends Duck { .... };
超类挖的一个坑,每个子类都要来填,增加工作量,复杂度O(N^2)。不是好的设计方式
需要新的设计方式,应对项目的扩展性,降低复杂度:
1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现;
2)鸭子哪些功能是会根据新需求变化的?叫声、飞行...
用策略模式来解决新需求
接口:
public interface FlyBehavior { void fly();}
public interface QuackBehavior { void quack();};
好处:新增行为简单,行为类更好的复用,组合更方便。既有继承带来的复用好处,没有挖坑
重新设计的鸭子项目:
public abstract class Duck { FlyBehavior mFlyBehavior; QuackBehavior mQuackBehavior; public Duck() { } public void Fly() { mFlyBehavior.fly(); } public void Quack() { mQuackBehavior.quack(); } public abstract void display(); }
绿头鸭、石头鸭:
public class GreenHeadDuck extends Duck { public GreenHeadDuck() { mFlyBehavior = new GoodFlyBehavior(); //实现了飞行行为接口的类(可以多个) mQuackBehavior = new GaGaQuackBehavior(); //实现了叫声接口的类(可以多个) } @Override public void display() {...} }
策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。
经验:多用组合来实现设计。
更详细的解释参考:http://www.cnblogs.com/zuoxiaolong/p/pattern8.html