设计模式(9):装饰模式 Decorator

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

装饰模式 Decorator

问题:

You want to add behavior or state to individual objects at run-time. Inheritance is not feasible because it is static and applies to an entire class..

意图:

  • Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
  • Client-specified embellishment of a core object by recursively wrapping it.
  • Wrapping a gift, putting it in a box, and wrapping the box.

代码

例:在游戏里面相当多,99%的游戏系统都可以给角色换装,但不一定彩用了装饰模式,如果用了的话,后续进行扩展(时装)等就比较简单了,这里来个demo简单的给车换装备。

代码1:包含两个部件的车,以及它的“裸装”(进入游戏送的)

package com.xdnote.DesignPattern.structural.decorator;

public abstract class Car {

    public String body ;
    public String engine ;
    public abstract void setBody(String car);
    public abstract void setEngine(String car);

    public void show() {
        System.out.println("最终结果:");
        System.out.println(this.body);
        System.out.println(this.engine);
    }
}

public class DefaultCar extends Car {

    public DefaultCar(){
        this.setBody("普通车身");
        this.setEngine("普通引擎");
    }
    @Override
    public void setBody(String body) {
        System.out.println("装备普通车身");
        this.body = body;
    }

    @Override
    public void setEngine(String engine) {
        System.out.println("装备普通引擎");
        this.engine = engine;
    }

}

代码二:装饰车,即是车,也是零件。(可换装备)


/**
 * @author xdnote.com
 * 装饰类,装饰模式的核心.继承并实现主类
 * 注意,这里我把这个类也定为抽象类,因为具体的装饰任务应该都由子类去完成.这里定义了一个抽象方法decorator
 * 
 * */
public abstract class DecoratorCar extends Car{

    /**
     * 构造方法,参数为想要被装饰的对象(车)
     * */
    public DecoratorCar(Car car) {
        this.body = car.body;
        this.engine = car.engine;
        this.decorator();
    }
    /**
     * 装饰(抽象)方法,由具体子类实现
     * */
    public abstract void decorator();

    @Override
    public void setBody(String body) {
        this.body = body;
    }
    @Override
    public void setEngine(String engine) {
        this.engine = engine;
    }

}

代码三:不做说明

public class BodyLv1 extends DecoratorCar{
    public BodyLv1(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备1级车身");
        this.setBody("1级车身");
    }
}
public class BodyLv2 extends DecoratorCar {

    public BodyLv2(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备2级车身");
        this.setBody("2级车身");
    }
}
public class BodyLv3 extends DecoratorCar{

    public BodyLv3(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备3级车身");
        this.setBody("3级车身");
    }

    public void setBody(String body){
        this. body =  body;
        System.out.println(">>>>经过3级车身改装,外观牛B了");
    }
}
public class EngineLv1 extends DecoratorCar {

    public EngineLv1(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备1级引擎");
        this.setEngine("1级引擎");
    }
}
public class EngineLv2 extends DecoratorCar {

    public EngineLv2(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备2级引擎");
        this.setEngine("2级引擎");
    }

    public void setEngine(String engine){
        this.engine = engine;
        System.out.println(">>>>经过2级引擎改装,性能加强了");
    }
}
public class EngineLv3 extends DecoratorCar {

    public EngineLv3(Car car) {
        super(car);
    }

    @Override
    public void decorator(){
        System.out.println("装备3级引擎");
        this.setEngine("3级引擎");
    }
}

代码四:客户端使用

      public static void main( String[] args ) {
          Car car1 = new DefaultCar();
          car1.show();
          System.out.println("-------");
          Car car2 = new EngineLv1(new DefaultCar());
          car2.show();
          System.out.println("-------");
          Car car3 = new BodyLv2(new EngineLv3(new DefaultCar()));
          car3.show();
          System.out.println("-------");
          Car car4 = new EngineLv3( new BodyLv2( new EngineLv1(new DefaultCar())));
          car4.show();
          System.out.println("-------");
          Car car5 = new BodyLv1(new BodyLv2(new BodyLv3(new EngineLv3(new EngineLv2(new EngineLv1(new DefaultCar()))))));
          car5.show();
      }

小结

装饰模式 Decorator

  • 使用频率:

    装饰模式相对于组合模式来说,每个点上只有一个对象,使用的场景会多一些,但在Web编程中也是挺少见的。

  • 利弊影响:

    有了这个模式后,安全性可以得到很大保障,特别是对一些热插拔思想的代码很有用。