定义

  • 在不修改原对象的情况下, 拓展对象的功能
  • 符合”组合优于继承” 的设计原则
  • 分离开核心功能与非核心的扩展功能。我们可以将核心功能放到实际类上,其他非核心装饰类的功能放到装饰类上

    对比

    不修改原对象, 而拓展对象的功能, 可以使用两种方式

  • 对类进行继承, 然后在子类中拓展功能, 最后使用子类

  • 新建一个包装类, 然后对原类进行组合, 最后使用这个包装类

    继承

  • 当功能种类多, 功能之间的组合多的时候, 需要每一种功能组合的情况都创建一个子类, 容易造成子类爆炸

    组合

  • 功能的实现可以通过包装类, 对于继承中容易造成子类爆炸的功能组合情况, 可以通过嵌套包装来实现

核心角色

  1. Component接口

在我们上面的例子中,Component接口相当于汽车接口,所有的被包装类、包装类,都继承于这个接口。

  1. ConcreteComponent类

ConcreteComponent类是被包装的实现类。在例子中,奔驰汽车、宝马汽车、特斯拉汽车都属于这个角色。

  1. Decorator抽象类

所有的包装类,都继承自Decorator抽象类,而Decorator类又实现了Component接口,这么做是为了实现多层嵌套包装。

  1. ConcreteDecorator类

具体的包装类,用于扩充被包装类的功能,比如例子中的自动驾驶功能、飞行功能扩展
装饰器模式 - 图1

示例

image.png

Component 角色 —> 接口, 原始类的接口

  1. public interface Car {
  2. void run();
  3. }

ConcreteComponent 角色 —> 接口的实现类, 既各个原始类

  1. public class BenzCar implements Car {
  2. @Override
  3. public void run() {
  4. System.out.println("奔驰开车了!");
  5. }
  6. }
  7. public class BmwCar implements Car {
  8. @Override
  9. public void run() {
  10. System.out.println("宝马开车了!");
  11. }
  12. }
  13. public class TeslaCar implements Car {
  14. @Override
  15. public void run() {
  16. System.out.println("特斯拉开车了!");
  17. }
  18. }

Decorator 角色 —> 装饰器的抽象类

  1. public class CarDecorator implements Car {
  2. protected Car decoratedCar;
  3. public CarDecorator(Car decoratedCar) {
  4. this.decoratedCar = decoratedCar;
  5. }
  6. public void run() {
  7. decoratedCar.run();
  8. }
  9. }

注意:

  • 装饰器的抽象类一定要实现原始类的接口
    • 让每一个装饰器本身也可以被更外层的装饰器所包装,包装的方式就是把Car对象作为参数传递给构造器
    • 目的是为了实现嵌套装饰

功能一

  1. public class AutoCarDecorator extends CarDecorator {
  2. public AutoCarDecorator(Car decoratedCar) {
  3. super(decoratedCar);
  4. }
  5. @Override
  6. public void run() {
  7. decoratedCar.run();
  8. autoRun();
  9. }
  10. private void autoRun() {
  11. System.out.println("开启自动驾驶");
  12. }
  13. }

功能二

  1. public class FlyCarDecorator extends CarDecorator {
  2. public FlyCarDecorator(Car decoratedCar) {
  3. super(decoratedCar);
  4. }
  5. @Override
  6. public void run() {
  7. decoratedCar.run();
  8. fly();
  9. }
  10. private void fly() {
  11. System.out.println("开启飞行汽车模式");
  12. }
  13. }

客户端 —> 包装和嵌套包装调用

  1. public class Client {
  2. public static void main(String[] args) {
  3. Car benzCar = new BenzCar();
  4. Car bmwCar = new BmwCar();
  5. Car teslaCar = new TeslaCar();
  6. //创建自动驾驶的奔驰汽车
  7. CarDecorator autoBenzCar = new AutoCarDecorator(benzCar);
  8. //创建飞行的、自动驾驶的宝马汽车 --> 嵌套包装
  9. CarDecorator flyAutoBmwCar = new FlyCarDecorator(new AutoCarDecorator(bmwCar));
  10. benzCar.run();
  11. bmwCar.run();
  12. teslaCar.run();
  13. autoBenzCar.run();
  14. flyAutoBmwCar.run();
  15. }
  16. }

实际示例

装饰器模式 - 图3