1 定义

装饰器(Decorator)模式,也称为包装(Wrapper)模式,是继承关系的一种替代方案。指在不改变对象结构的情况下,动态的给对象添加一些功能。

2 优缺点

2.1 优点

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

2.2 缺点

  • 装饰器模式会增加许多子类,过度使用会增加程序得复杂性。

3 装饰器模式的结构与实现

装饰器模式的类图如下所示:

 装饰器模式主要包含以下角色。

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

4 代码实现

大家应该都看过一部日本动画片《铁甲小宝》,里面的一号机器人---卡布达,在平时的时候,他是一个笨笨的但是特别可爱的机器人,当他们需要争夺和平星进行比赛的时候,他就会变身,成为战斗力爆表的卡布达,最后,他获得了他的卡布达巨人,让战斗力又提升了一个档次。这个例子中,变身卡布达以及卡布达巨人就是普通卡布达的装饰,增强卡布达的能力。

4.1 卡布达接口KaBuDa

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-09-07 12:01
 **/
public interface KaBuDa {

    /**
     * 示人的形象
     */
    void display();
}

4.2 装饰器代码

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-09-07 14:51
 **/
public class Decorator implements KaBuDa {

    private KaBuDa kaBuDa;

    public Decorator(KaBuDa kaBuDa) {
        this.kaBuDa = kaBuDa;
    }


    @Override
    public void display() {
        this.kaBuDa.display();
    }
}

4.3 普通卡布达CommonKaBuDa

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-09-07 14:49
 **/
public class CommonKaBuDa implements KaBuDa{

    @Override
    public void display() {
        System.out.println("我是普通卡布达,卡布卡布卡布");
    }
}

4.4 变身后的卡布达TransfigurationKaBuDa

**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-09-07 15:20
 **/
public class TransfigurationKaBuDa extends Decorator{

    public TransfigurationKaBuDa(KaBuDa kaBuDa) {
        super(kaBuDa);
    }

    @Override
    public void display() {
        super.display();
        System.out.println("启动超级变换形态---超级变换形态");
    }
}

4.5 卡布达巨人GiantKaBuDa

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-09-07 15:49
 **/
public class GiantKaBuDa extends Decorator{

    public GiantKaBuDa(KaBuDa kaBuDa) {
        super(kaBuDa);
    }

    @Override
    public void display() {
        super.display();
        System.out.println("超级卡布达巨人");
    }
}

4.6 主程序

/**
 * @program: design-pattern-learning
 *
 * @author: zgr
 * @create: 2021-09-07 11:57
 **/
public class MainClass {
    public static void main(String[] args) {
        System.out.println("-----------------1--------------------");
        KaBuDa commonKaBuDa = new CommonKaBuDa();
        commonKaBuDa.display();
        System.out.println("-----------------2--------------------");
        System.out.println("蜻蜓队长: 比赛开始");
        System.out.println("-----------------3--------------------");
        KaBuDa transfigurationKaBuDa = new TransfigurationKaBuDa(commonKaBuDa);
        transfigurationKaBuDa.display();
        System.out.println("-----------------4--------------------");
        System.out.println("呼唤卡布达巨人");
        System.out.println("-----------------5--------------------");
        KaBuDa giantKaBuDa = new GiantKaBuDa(transfigurationKaBuDa);
        giantKaBuDa.display();
    }
}

4.7 运行结果

 结果看到,对卡布达不断进行进行装饰,最后达到拥有卡布达巨人的无敌状态。

5 装饰器模式的简化

一般情况下,装饰器模式没有抽象的被装饰接口,只有一个具体的被装饰对象,这是就考虑去掉Component类(接口),把Decorator作为一个ConcreteComponent的子类。如下图所示:

6 引用

1.《大话设计模式》

2.装饰器模式(装饰设计模式)详解

3.java设计模式-装饰器模式(Decorator)

7 源代码

https://github.com/airhonor/design-pattern-learning/tree/main/src/com/hz/design/pattern/decorator

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐