Java设计模式之结构型-装饰器模式 (Decorator)

文章示例代码

装饰器模式对于笔者来说,印象还是比较深刻的。因为当年笔者考软件设计师的设计模式大题考的就是这个模式,差点阵亡。

附链

你也可以在这些平台阅读本文:

  • 语雀
  • 个人博客

定义

动态地为一个对象添加一些额外的职责。

在扩展原有对象功能上,装饰器模式比继承的方式更加灵活。

模式中的角色

  • 抽象构建(Component):定义一个抽象接口(可以是抽象类),用以给对象动态地添加职责。
  • 具体构建(ConcreteComponent):定义一个具体的对象,实现Component接口。
  • 抽象装饰者(Decorator):继承Component,用有Component的职责,同时也可以扩展职责。
  • 具体装饰者(ConcretorDecorator):负责给具体的构建对象添加职责,同时可以定义额外的职责。

场景示例

笔者作为一点点的重度爱好者,这里就以奶茶为例。

创建抽象构建

/**
 * @author zhh
 * @description 抽象奶茶类
 * @date 2020-02-13 23:30
 */
public abstract class AbstractMilkyTea {

    /**
     * 描述
     */
    protected abstract String desc();

    /**
     * 价格
     */
    protected abstract int price();
}

创建具体构建

/**
 * @author zhh
 * @description 具体奶茶类
 * @date 2020-02-13 23:35
 */
public class MilkyTea extends AbstractMilkyTea {

    @Override
    protected String desc() {
        return "奶茶";
    }

    @Override
    protected int price() {
        return 7;
    }
}

创建抽象装饰者

/**
 * @author zhh
 * @description 抽象装饰者类
 * @date 2020-02-13 23:37
 */
public abstract class AbstractDecorator extends AbstractMilkyTea {

    private AbstractMilkyTea abstractMilkyTea;

    public AbstractDecorator(AbstractMilkyTea abstractMilkyTea) {
        this.abstractMilkyTea = abstractMilkyTea;
    }

    @Override
    protected String desc() {
        return this.abstractMilkyTea.desc();
    }

    @Override
    protected int price() {
        return this.abstractMilkyTea.price();
    }
}

这里抽象装饰者继承了抽象奶茶类。

这个时候,具体奶茶类和抽象装饰者类都作为抽象奶茶类的子类。

我们可以通过具体奶茶类和抽象装饰者类继承的父类(抽象奶茶类)进行组合让这两个子类建立关系。

创建具体装饰者

/**
 * @author zhh
 * @description 糖装饰者
 * @date 2020-02-13 23:58
 */
public class SugarDecorator extends AbstractDecorator {

    public SugarDecorator(AbstractMilkyTea abstractMilkyTea) {
        super(abstractMilkyTea);
    }

    @Override
    protected String desc() {
        return super.desc() + " 加糖";
    }

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

/**
 * @author zhh
 * @description 红豆装饰者
 * @date 2020-02-14 00:14
 */
public class RedBeanDecorator extends AbstractDecorator {

    public RedBeanDecorator(AbstractMilkyTea abstractMilkyTea) {
        super(abstractMilkyTea);
    }

    @Override
    protected String desc() {
        return super.desc() + " 加红豆";
    }

    @Override
    protected int price() {
        return super.price() + 2;
    }
}

/**
 * @author zhh
 * @description 珍珠装饰者
 * @date 2020-02-13 23:56
 */
public class PearlDecorator extends AbstractDecorator {

    public PearlDecorator(AbstractMilkyTea abstractMilkyTea) {
        super(abstractMilkyTea);
    }

    @Override
    protected String desc() {
        return super.desc() + " 加珍珠";
    }

    @Override
    protected int price() {
        return super.price() + 2;
    }
}

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-14 00:21
 */
public class Test {

    public static void main(String[] args) {
        AbstractMilkyTea abstractMilkyTea = new MilkyTea();
        abstractMilkyTea = new SugarDecorator(abstractMilkyTea);
        abstractMilkyTea = new PearlDecorator(abstractMilkyTea);
        System.out.println(abstractMilkyTea.desc() + " 的销售价格是:" + abstractMilkyTea.price());

        abstractMilkyTea = new MilkyTea();
        abstractMilkyTea = new RedBeanDecorator(abstractMilkyTea);
        abstractMilkyTea = new PearlDecorator(abstractMilkyTea);
        System.out.println(abstractMilkyTea.desc() + " 的销售价格是:" + abstractMilkyTea.price());
    }
}

测试类输出的结果如下:

奶茶 加糖 加珍珠 的销售价格是:10
奶茶 加红豆 加珍珠 的销售价格是:11

类结构图

以上示例类的结构图如下所示
Java设计模式之结构型-装饰器模式 (Decorator)_第1张图片

总结

适用场景

  • 给一个类添加额外的职责
  • 动态的为一个对象添加功能同时可以动态撤销

优点

  • 比继承更加灵活,易扩展。可以在不改变原有对象的情况下给一个对象扩展功能。
  • 解耦。装饰类和被装饰者可以独立变化,不会相互耦合。

缺点

会导致代码和类的骤增,增加程序复杂性。

参考

  • 《Head First 设计模式》
  • 《大话设计模式》
  • 维基百科-修饰模式
  • 菜鸟教程-装饰器模式

你可能感兴趣的:(设计模式)