笔头云 笔头云
首页
设计模式
SQL教程
Redis
归档
关于
友链

笔头云

非淡泊无以明志,非宁静无以致远。
首页
设计模式
SQL教程
Redis
归档
关于
友链
  • 设计原则
  • 设计模式
  • 单例模式
  • 工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 代理模式
  • 装饰器模式
    • 定义
    • 结构
    • 优点
    • 缺点
    • 应用场景
    • 示例代码1
    • 示例代码2
  • 门面模式
  • 桥接模式
  • 享元模式
  • 组合模式
  • 策略模式
  • 模板方法模式
  • 观察者模式
  • 责任链模式
  • 状态模式
  • 迭代器模式
  • 访问者模式
  • 中介模式
  • 命令模式
  • 解释器模式
  • 备忘录模式
  • 设计模式
笔头云
2023-11-01
目录

装饰器模式

# 装饰器模式

装饰器模式是一种非常有用的设计模式,可以在保持代码灵活性和可维护性的同时,动态地扩展对象的功能。

# 定义

装饰器模式,也叫作包装器模式,是一种结构型设计模式,指在不改变原有对象的基础上,动态地给一个对象添加一些额外的功能。

# 结构

抽象组件(Component): 抽象组件定义了被装饰对象和装饰器共同实现的接口或抽象类。它可以是抽象类或接口,提供了装饰器和被装饰对象的一致性接口。
具体组件(Concrete Component): 具体组件是被装饰的对象,实现了抽象组件定义的接口或抽象类。它是装饰器模式中的原始对象,也是装饰器所装饰的目标。
抽象装饰器(Decorator): 抽象装饰器是一个抽象类或接口,它继承或实现了抽象组件的接口或抽象类。持有抽象组件的引用,并定义了一个与抽象组件一致的接口,用于封装具体装饰器和被装饰对象的交互。
具体装饰器(Concrete Decorators): 具体装饰器是抽象装饰器的子类,它实现了抽象装饰器定义的接口,在运行时可以动态地给被装饰对象添加新的行为或功能。

装饰器模式

- img: https://bitouyun.com/images/design-pattern/decorator.png
  link: https://bitouyun.com/images/design-pattern/decorator.png
  name: 装饰器模式
1
2
3

提示

比较简单的场景下可以省略抽象组件和抽象装饰器。

# 优点

灵活性:装饰器模式允许在不改变原始对象的情况下,通过包装器对象来动态添加功能。可以根据需要组合多个装饰器,以实现不同的组合效果,从而提供更大的灵活性和可定制性。
开闭原则:通过装饰器模式,可以在不修改现有代码的情况下添加新的功能。这符合开闭原则,即对扩展开放,对修改关闭。
单一职责原则:装饰器模式允许将功能划分为多个单一的装饰器类,每个装饰器类只关注一种功能的添加或修改,从而遵循了单一职责原则。
代码复用:装饰器模式可以通过组合不同的装饰器类来实现代码的复用。不同的装饰器可以按照需要进行组合,以创建不同的组合效果。

# 缺点

复杂性增加:使用装饰器模式会增加一些额外的类和对象,从而增加了系统的复杂性。如果使用不当,可能会导致过多的装饰器类,使得代码难以理解和维护。
运行时开销:由于装饰器模式涉及包装器对象的嵌套调用,可能会在运行时产生一些性能开销。每个装饰器都需要进行额外的处理,可能会对系统的性能产生一定的影响。

# 应用场景

在不改变现有对象结构的情况下,动态地给对象添加功能。
需要灵活地组合和配置对象的功能,以满足不同的需求。
需要对对象的功能进行扩展,但是使用继承会导致类爆炸的情况,或者不希望通过继承来实现功能扩展。
需要在运行时动态地添加、修改或移除对象的功能。
常见的使用场景包括:输入/输出流处理、身份验证和授权、缓存系统、日志记录等。

装饰器模式与代理模式的区别

代理模式是控制对对象的访问,为其他对象提供一个代理以控制对这个对象的访问。代理模式可以在访问对象时添加额外的逻辑。
装饰器模式注重对对象功能的增强和扩展,而代理模式注重对对象的控制访问。
装饰器模式通过包装器对象来包装原始对象,形成一条装饰链;代理模式通过代理对象来控制对原始对象的访问。
装饰器模式保持了原始对象的接口完整性,客户端可以透明地使用装饰后的对象;代理模式可以隐藏原始对象的细节,客户端可能无法直接访问原始对象。
实际上,装饰器模式可以看作是一种特殊的代理模式,其中代理对象的主要职责是增强原始对象的功能。因此,装饰器模式和代理模式可以相互补充,并在某些情况下可以互换使用。

# 示例代码1

场景1

添加用户业务,使用装饰器模式记录日志时间。

    /**
     * 日志记录接口
     * 抽象组件,定义了被装饰对象和装饰器共同实现的接口或抽象类
     */
    public interface Logger {
      // 记录日志
      void log(String message);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    /**
     * 日志实现类
     * 具体组件,是被装饰的对象,实现或继承了抽象组件定义的接口或抽象类。
     */
    @Slf4j
    public class SimpleLogger implements Logger {
      @Override
      public void log(String message) {
        log.info("日志:{}", message);
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
     * 日志装饰器抽象类
     * 抽象装饰器,继承或实现了抽象组件的接口或抽象类,持有一个抽象组件的引用。
     */
    public abstract class LoggerDecorator implements Logger {
      // 持有抽象组件的引用
      protected Logger logger;
    
      public LoggerDecorator(Logger logger) {
        this.logger = logger;
      }
    
      // 封装具体装饰器和被装饰对象的交互
      @Override
      public void log(String message) {
        logger.log(message);
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /**
     * 记录日志时间类
     * 具体装饰器类,是抽象装饰器的子类,实现抽象装饰器定义的接口方法,可以动态给被装饰对象添加新的行为或功能。
     */
    @Slf4j
    public class TimeLoggerDecorator extends LoggerDecorator {
      public TimeLoggerDecorator(Logger logger) {
        super(logger);
      }
    
      public void log(String message) {
        log.info("时间:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        logger.log(message);
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
     * 测试类
     */
    public class Client {
      public static void main(String[] args) {
        // 日志实现类
        Logger logger = new SimpleLogger();
        // 日志装饰器
        logger = new TimeLoggerDecorator(logger);
        // 记录日志
        logger.log("创建用户");
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // Make sure to add code blocks to your code group

    # 示例代码2

    场景2

    使用装饰器模式实现用户权限控制,限制用户对系统的操作。

      /**
       * 用户接口
       * 抽象组件,定义了被装饰对象和装饰器共同实现的接口或抽象类
       */
      public interface User {
          void operate(String action);
      }
      
      1
      2
      3
      4
      5
      6
      7
      /**
       * 普通用户
       * 具体组件,是被装饰的对象,实现或继承了抽象组件定义的接口或抽象类。
       */
      @Slf4j
      public class NormalUser implements User {
      
          private String username;
      
          public NormalUser(String username) {
              this.username = username;
          }
      
          @Override
          public void operate(String action) {
              log.info("{}执行{}操作", username, action);
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      /**
       * 抽象装饰器类
       * 继承或实现了抽象组件的接口或抽象类,持有一个抽象组件的引用。
       */
      public abstract class UserDecorator implements User {
      
          // 持有一个用户接口引用
          protected  User user;
      
          public UserDecorator(User user) {
              this.user = user;
          }
      
          @Override
          public void operate(String action) {
              user.operate(action);
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      /**
       * 权限检查装饰器
       * 具体装饰器类,是抽象装饰器的子类,实现抽象装饰器定义的接口方法,可以动态给被装饰对象添加新的行为或功能。
       */
      @Slf4j
      public class PermissionCheckUserDecorator extends UserDecorator { 
        
        // 允许的操作列表
        private List<String> allowOperations;
      
        public PermissionCheckUserDecorator(User user, List<String> allowOperations) {
          super(user);
          this.allowOperations = allowOperations;
        }
      
        public void operate(String action) {
          if (allowOperations.contains(action)) {
            super.operate(action);
          } else {
            log.error("没有{}权限", action);
          }
        }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      /**
       * 测试类
       */
      public class Client {
          public static void main(String[] args) {
              User user = new NormalUser("Mike");
              // 允许的操作
              List<String> allowOperations = Arrays.asList("add", "update", "select");
              user = new PermissionCheckUserDecorator(user, allowOperations);
              user.operate("add");
              user.operate("update");
              user.operate("select");
              user.operate("delete");
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      // Make sure to add code blocks to your code group
      #结构型模式#设计模式
      上次更新: 2023/11/17, 09:38:49
      代理模式
      门面模式

      ← 代理模式 门面模式→

      最近更新
      01
      FRP内网穿透docker部署 工具
      05-07
      02
      Office Util办公工具 工具
      01-14
      03
      Git常用命令
      01-16
      更多文章>
      Theme by Vdoing | Copyright © 2023-2025 鲁ICP备2023014898号 公安备案号:37020302372159
      • 跟随系统
      • 浅色模式
      • 深色模式
      • 阅读模式
      ×