一、装饰器模式定义

1.装饰器模式,也称为包装模式,是指在不改变原有对象的基础之上,将功能附件到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式

2.装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态的扩展类的功能

3.原理:让装饰器实现被包装类(ConcreteComponent)相同的接口(Component)(使得装饰器与被扩展类类型一致),并在构造函数中传入该接口(Component)对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能了。而且由于装饰器与被包装类属于同一类型(均为Component),且构造函数的参数为其实现接口类(Component),因此装饰器模式具备嵌套扩展功能,这样我们就能使用装饰器模式一层一层的对最底层被包装类进行功能扩展了

4.装饰器模式应用场景:

  A.用于扩展一个类的功能或给一个类添加附件职责

  B.动态的给一个对象添加功能,这些功能可以再动态的撤销

  C.需要为一批的兄弟类进行改装或加装功能

 

二、装饰器示例

1.装饰器模式主要包含四种角色:

  A.抽象组件(Component):可以是一个接口或抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为

  B.具体组件(ConcreteComponent):实现/继承Component的一个具体对象,也即被装饰对象

  C.抽象装饰器(Decorator):通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component抽象组件;其实现一般是一个抽象类,主要是为了让其他子类按照其构造形式传入一个Component抽象组件,这是强制的通用行为(当然,如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直接实现一个具体装饰器(ConcreteDecorator)即可)

  D.具体装饰器(ConcreteDecorator):Decorator的具体实现类,理论上,每个ConcreteDecorator都扩展了Component对象的一种功能

 

2.代码

/**
 * 被装饰对象的基类,用来规范准备附加的功能  抽象
 */
public abstract class Battercake {

    protected abstract String getMsg();

    protected abstract int getPrice();

}

/**
 * 具体被装饰的类
 */
public class BaseBattercake extends Battercake {

    @Override
    protected String getMsg() {
        return "煎饼";
    }

    @Override
    protected int getPrice() {
        return 5;
    }
}

/**
 * 装饰类的抽象类
 */
public abstract class BattercakeDecorator extends Battercake {

    private Battercake battercake;

    public BattercakeDecorator(Battercake battercake){
        this.battercake = battercake;
    }

    @Override
    protected String getMsg() {
        return this.battercake.getMsg();
    }

    @Override
    protected int getPrice() {
        return this.battercake.getPrice();
    }

}

public class EggDecorator extends BattercakeDecorator {

    public EggDecorator(Battercake battercake){
        super(battercake);
    }

    @Override
    protected String getMsg() {
        return super.getMsg()+"+1个鸡蛋";
    }

    @Override
    protected int getPrice() {
        return super.getPrice()+1;
    }
}

public class DecoratorTest {

    public static void main(String[] args) {
        Battercake battercake = new BaseBattercake();
        battercake = new EggDecorator(battercake);
        System.out.println(battercake.getMsg()+"---"+battercake.getPrice());
    }
}

 

3.装饰器模式和代理模式对比

  A.装饰器模式强调自身功能的扩展。Decorator所做的就是增强ConcreteComponent的功能(也有可能减弱功能),主题对象为ConcreteComponent,着重类功能的变化

  B.代理模式强调对代理过程的控制。Proxy完全掌握对RealSubject的访问控制,因此,Proxy可以决定对RealSubject进行功能扩展,功能缩减甚至功能散失(不调用RealSubject方法),主体对象为Proxy

 

4.装饰器模式优缺点

  A.优点

    a.装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用

    b.通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果

    c.装饰器完全遵循开闭原则

  B.缺点

    a.会出现更多的代码,更多的类,增加程序复杂性

    b.动态装饰时,多层装饰时会更复杂