子类复子类,子类何其多
示例:
假如我们需要为游戏中开发一种坦克,除了各种不同型号的坦克外,我们还希望在不同场合为其添加以下一种或者多种功能:比如红外线夜视,水陆两栖功能,卫星定位功能等
代码:(第一版本)
//抽象坦克类
public abstract class Tank{
public abstract shot();//发射
public abstract run();//跑动
}
//坦克子类
public class TankA extends Tank{
}
public class TankB extends Tank{
}
public class TankC extends Tank{
}
//功能接口
public interface flyable{
public void fly();
}
public interface swinable{
public void swin();
}
//各种不同功能的组合(满足需求的设计)
public class TankAWithFly extends TankA implements flyable{//能飞的坦克
}
public class TankAWithSwin extends TankA implements swinable{//能下水的坦克
}
public class TankAWithFlyAndSwin extends TankA implements swinable{//能飞,能下水的坦克
}
问题:
每一个功能的增加都会产生一个子类
解决办法:装饰模式的运用
何时用:解决主体类在多个方向上的扩展问题
动机:上述描述的问题根源在于我们"过度地使用了类或接口继承来扩展对象的功能",由于继承为类型引入到静态特质(我们要想获取一个功能,我们在编译的时候要建一个类),使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀
如何使"对象功能的扩展"能够根据需要来动态地实现?同时避免扩展功能的增多带来子类的膨胀问题?从而使得任何"功能扩展变化"所导致的影响将为最低?
意图:
动态地给一个对象增加一些额外的职责,就增加功能而言,修饰者模式比生成子类更为灵活.
package decorator; //抽象类 public abstract class Tank { public abstract void shot(); public abstract void run(); } package decorator; /** * 坦克A * @author Administrator * */ public class TankA extends Tank { @Override public void run() { System.out.println("Tank A 开始跑了"); } @Override public void shot() { System.out.println("Tank A 开始发射"); } } package decorator; public abstract class Decorator extends Tank { private Tank tank; public Decorator(Tank tank) { this.tank = tank; } @Override public void run() { tank.run(); } @Override public void shot() { tank.shot(); } public Tank getTank() { return tank; } public void setTank(Tank tank) { this.tank = tank; } } package decorator; /** * 在run方法前进行相关的处理 如 进入书中 等 * @author Administrator * */ public class DecoratorInWater extends Decorator { public DecoratorInWater(Tank tank) { super(tank); } @Override public void run() { System.out.println("进入水中.."); super.run(); } } package decorator; /** * 装饰tank类 使其具有 发射具有红外功能 * @author Administrator * */ public class DecoratorShot extends Decorator { public DecoratorShot(Tank tank) { super(tank); } @Override public void shot() { System.out.println("使其具有红外功能的坦克!"); super.shot(); } } package decorator; public class App { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Tank tankA=new TankA(); Decorator decTankA=new DecoratorShot(tankA); Decorator decTankB=new DecoratorInWater(decTankA); decTankB.shot(); decTankB.run(); } }
通过采用组合、而非继承的手法,Decorator模式实现了在运动时动态的扩展了对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的"灵活性差"和"多子类衍生问题"