羿先生的学习笔记[7]: Decorator设计模式
假设我们经营着一家坦克工厂。我们已经实现了一个坦克的接口Tank:
public interface Tank {
public void drive();
public void fire();
}
和实现了坦克接口的抽象类:
public abstract class AbstractTank implements Tank {
protected String type;
@Override
public void drive() {
System.out.println(type + " moving forward!");
}
@Override
public void fire() {
System.out.println(type + " main gun open fire!");
}
@Override
public String toString() {
return type + "\n" + "main gun";
}
}
以及两种具体的坦克:59和谢尔曼
public class Tank59 extends AbstractTank{
public Tank59() {
type = "59式";
}
}
public class Sherman extends AbstractTank {
public Sherman() {
type = "Sherman";
}
}
现在我们的坦克工厂开工了。
我们的坦克目前只有一门主炮,客户希望能在我们的坦克上加装雷达与机枪。如果我们在每类坦克的代码中都进行修改,那么我们坦克类型越多,就会有越大的、高度重复的工作量。我们对此的解决方法就是使用Decorator设计模式。Decorator设计模式本质上是给已有的类进行打包并加入新的具体特性。
为了给我们的坦克加上机枪和雷达,我们首先用一个TankDecorator抽象类实现Tank接口:
public abstract class TankDecorator implements Tank{
protected Tank tank;
}
并分别使用两个具体的分别表示机枪和雷达的装饰类去实现:
public class TankWithMachineGun extends TankDecorator{
public TankWithMachineGun(Tank tank){
this.tank = tank;
}
@Override
public void drive() {
tank.drive();
}
@Override
public void fire() {
tank.fire();
System.out.println("Machine gun open fire!");
}
@Override
public String toString() {
return tank.toString() + "\n" + "machine gun";
}
}
public class TankWithRadar extends TankDecorator{
public TankWithRadar(Tank tank){
this.tank = tank;
}
@Override
public void drive() {
tank.drive();
System.out.println("Radar is detecting enemy.");
}
@Override
public void fire() {
tank.fire();
}
@Override
public String toString() {
return tank.toString() + "\n" + "radar";
}
}
以机枪为例,TankWithMachineGun类实质是把一个坦克对象包装起来,调用fire()方法时先调用包装的坦克的fire方法再执行机枪开火的代码。
现在我们生产一辆安装有雷达和机枪的59坦克并进行一些测试:
public class Test {
public static void main(String[] args) {
Tank tank59 = new Tank59();
Tank tank59_1 = new TankWithMachineGun(tank59);//59改-1
Tank tank59_2 = new TankWithRadar(tank59_1);//59改-2
System.out.println(tank59_2);//打印参数
tank59_2.drive();//移动测试
tank59_2.fire();//射击测试
}
}
输出:
59式
main gun
machine gun
radar
59式 moving forward!
Radar is detecting enemy.
59式 main gun open fire!
Machine gun open fire!
可见我们已经成功地完成了组装。
以下是Decorator模式结构的一个图解:
Decorator模式的特点在于:
- 可以很容易的重复添加一个特性
- 可以递归的嵌套多个装饰
- 对客户透明,客户不知道某个具体组件有没有被装饰
- 符合开发-闭合原则:通过新增具体组件和具体装饰者来达到扩展的目的
Decorator模式可以在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。当用过直接继承会产生过多的子类时,我们最好采用Decorator模式。