设计模式之装饰器模式详解

article/2025/8/27 20:29:06

设计模式之装饰器模式详解

文章目录

  • 设计模式之装饰器模式详解
    • 一、什么是装饰器模式
    • 二、装饰器模式的角色组成
    • 三、装饰器模式通用写法示例
    • 四、装饰器模式业务中的应用举例
    • 五、装饰器模式优缺点

一、什么是装饰器模式

装饰器模式(Decorator Pattern) 也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。

二、装饰器模式的角色组成

我们先来看下装饰器模式的通用类图:
在这里插入图片描述

  • 抽象组件(Component): 可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为;
  • 具体组件(ConcreteComponent): 实现/继承Component的一个具体对象,也即被装饰对象;
  • 抽象装饰器(Decorator): 通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个Component抽象组件,这是强制的通用行为(当然,如果系统中逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直接实现一个具体装饰器(ComcreteDecorator)即可);
  • 具体装饰器(ConcreteDecorator): Decorator的具体实现类,理论上,每个ConcreteDecorator都扩展了Component对象的一种功能;

三、装饰器模式通用写法示例

  1. 创建一个抽象组件Component来规定被装饰对象的行为

    /*** 抽象组件** @author zdp* @date 2022/9/3 17:48*/
    public abstract class Component {public abstract void execute();
    }
    
  2. 创建具体组件ConcreteComponent

    /*** 具体组件(需要被装饰的组件)** @author zdp* @date 2022/9/3 17:48*/
    public class ConcreteComponent extends Component {@Overridepublic void execute() {System.out.println("具体组件处理业务逻辑");}}
    
  3. 创建一个抽象装饰器Decorator

    /*** 抽象装饰器(继承、实现抽象组件,并持有抽象组件)** @author zdp* @date 2022/9/3 17:49*/
    public abstract class Decorator extends Component {/*** 抽象组件*/public Component component;public Decorator(Component component) {this.component = component;}/*** 将执行动作转发给组件本身执行,可以在转发前后做装饰** @author zdp* @date   2022/9/3 17:56*/public void execute() {component.execute();}
    }
    
  4. 创建具体装饰器ConcreteDecorator

    /*** 具体装饰器A继承抽象装饰器** @author zdp* @date 2022/9/3 17:49*/
    public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}/*** 具体组件动作执行前的装饰** @author zdp* @date   2022/9/3 17:58*/public void before(){System.out.println("ConcreteDecorator前置操作....");}/*** 具体组件动作执行后的装饰** @author zdp* @date   2022/9/3 17:58*/public void after(){System.out.println("ConcreteDecorator后置操作....");}/*** 组件本身执行的动作** @author zdp* @date   2022/9/3 18:01*/public void execute() {before();component.execute();after();}
    }
  5. 测试

    /*** decorator 通用写法测试** @author zdp* @date 2022/9/3 17:50*/
    public class Test {public static void main(String[] args) {//创建需要被装饰的组件Component component = new ConcreteComponent();//给对象透明的增加功能并调用Decorator decorator = new ConcreteDecorator(component);decorator.execute();}
    }
    

四、装饰器模式业务中的应用举例

需求:现系统中采用slf4j打印的日志为字符串格式,现使用装饰器模式将日志打印输出为Json格式

现系统中的存在Logger接口以及Logger的实现,Logger就可视为抽象组件,Logger的具体实现就为具体组件,现我们只需完成抽象装饰器及具体的装饰器实现即可

  1. 创建抽象装饰器DecoratorLogger

    /*** 抽象装饰器,持有并实现抽象组件Logger** @author zdp* @date 2022/9/3 18:44*/
    public abstract class DecoratorLogger implements Logger {protected Logger logger;public DecoratorLogger(Logger logger) {this.logger = logger;}@Overridepublic void info(String s) { }@Overridepublic void error(String s) { }// 其他实现方法省略....
    }
    
  2. 创建具体装饰器JsonLogger

    /*** 具体装饰器: Json-logger** @author zdp* @date 2022/9/3 18:47*/
    public class JsonLogger extends DecoratorLogger {public JsonLogger(Logger logger) {super(logger);}@Overridepublic void info(String message) {JSONObject obj = new JSONObject();obj.put("message", message);logger.info(obj.toString());}@Overridepublic void error(String message) {JSONObject obj = new JSONObject();obj.put("message", message);logger.error(obj.toString());}}
    
  3. 构造一个Factory

    /*** JsonLoggerFactory** @author zdp* @date 2022/9/4 22:28*/
    public class JsonLoggerFactory {public static JsonLogger getLogger(Class<?> clazz){return new JsonLogger(LoggerFactory.getLogger(clazz));}}
    
  4. 测试

    /*** JsonLogger Test* * @author zdp* @date 2022/9/3 17:50*/
    public class Test {private static final Logger logger = LoggerFactory.getLogger(Test.class);private static final Logger jsonLogger = JsonLoggerFactory.getLogger(Test.class);public static void main(String[] args) {logger.info(" logger info 日志打印....");jsonLogger.info(" jsonLogger info 日志打印....");System.out.println();logger.error("logger error日志打印....");jsonLogger.error("jsonLogger error日志打印....");}
    }
    

在这里插入图片描述

五、装饰器模式优缺点

  • 优点
    • 装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用
    • 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
    • 装饰器完全遵守开闭原则
  • 缺点
    • 从代码层面来看,使用装饰器模式会出现更多的代码,更多的类,增加程序复杂性
    • 动态装饰时,多层装饰时会更复杂

http://chatgpt.dhexx.cn/article/ADbq5Uh6.shtml

相关文章

TS装饰器

通过本文你可以知道什么 装饰器的发展历程JS和TS装饰器有何不同Angular中的装饰器到底是什么装饰器的定义&#xff0c;语法&#xff0c;作用reflect-meta是什么及如何使用 前言 我们平常开发中或多或少的听说或使用过装饰器&#xff0c;也切身感受到了它带给我们的便利。但是…

python的装饰器(函数装饰器)

作为许多语言都存在的高级语法之一&#xff0c;装饰器是你必须掌握的知识点。 装饰器&#xff08;Decorator&#xff09;&#xff1a;从字面上理解&#xff0c;就是装饰对象的器件。可以在不修改原有代码的情况下&#xff0c;为被装饰的对象增加新的功能或者附加限制条件或者帮…

python装饰器这一篇就够了

前言 什么是装饰器 实现原理 实现效果 适用场景 装饰器&#xff1a; 装饰器的写法 装饰器的拓展 装饰器的模板 什么是装饰器呢&#xff1f; 就是在特定条件下为某些函数再不改动函数体的时候为函数新添加一些功能&#xff0c;这就是装饰器 实现原理&#xff1a; …

【Python】闭包与装饰器

1.闭包 闭包的本质就是函数的嵌套定义&#xff0c;即在函数内部再定义函数 闭包有两种不同的方式&#xff0c;第一种是“返回一个函数名称”&#xff0c;第二种是在函数内部就“直接调用” 闭包的定义&#xff1a;在一个外函数中定义了一个内函数&#xff0c;内函数里运用了…

Python装饰器的通俗理解

看了这篇文章终于搞懂了装饰器&#xff0c;原文有少许错误&#xff0c;但无伤大雅&#xff0c;改正后转载于此&#xff0c;一起学习。 在学习Python的过程中&#xff0c;我相信有很多人和我一样&#xff0c;对Python的装饰器一直觉得很困惑&#xff0c;我也是困惑了好久&#x…

什么是装饰器?

一、引出装饰器概念 引入问题&#xff1a; 定义了一个函数&#xff0c;想在运行时动态的增加功能&#xff0c;又不想改动函数本身的代码&#xff1f; 示例&#xff1a; 希望对下列函数调用增加log功能&#xff0c;打印出函数调用&#xff1a; def f1(x): return x*2 d…

Python自定义装饰器

文章目录 1.闭包2.不带参数的装饰器3.带参数的装饰器4.不定长参数的装饰器5.多重装饰器修饰6.返回值是装饰器7.装饰器类 Python学习笔记—装饰器 装饰器&#xff1a;从生活角度理解&#xff0c;是对一个东西进行装饰&#xff0c;增加它本身的一些功能和内容&#xff1b; Python…

Python的装饰器

前言&#xff1a; &#x1f921; 作者简介&#xff1a;我是Morning&#xff0c;计算机的打工人&#xff0c;想要翻身做主人 &#x1f648; &#x1f648; &#x1f648; &#x1f3e0; 个人主页&#xff1a;Morning的主页 &#x1f4d5;系列专栏&#xff1a;&#…

装 饰 器

一&#xff0c;装饰器概念 装饰器本质上还是函数&#xff0c;让其它的函数在不做任何代码修改的情况下&#xff0c;增加额外的功能 所以说一句话&#xff1a;还是函数&#xff0c;记住奥 谈到一个原则&#xff1a;开发封闭原则 概念&#xff1a; 一个以函数作为参数并返回一…

学习TypeScript20(装饰器Decorator)

Decorator 装饰器是一项实验性特性&#xff0c;在未来的版本中可能会发生改变 它们不仅增加了代码的可读性&#xff0c;清晰地表达了意图&#xff0c;而且提供一种方便的手段&#xff0c;增加或修改类的功能 若要启用实验性的装饰器特性&#xff0c;你必须在命令行或tsconfig…

python装饰器详解

python中的装饰器(decorator)一般采用语法糖的形式&#xff0c;是一种语法格式。比如&#xff1a;classmethod&#xff0c;staticmethod&#xff0c;property&#xff0c;xxx.setter&#xff0c;wraps()&#xff0c;func_name等都是python中的装饰器。 装饰器&#xff0c;装饰的…

【Python】一文弄懂python装饰器(附源码例子)

目录 前言 一、什么是装饰器 二、为什么要用装饰器 三、简单的装饰器 四、装饰器的语法糖 五、装饰器传参 六、带参数的装饰器 七、类装饰器 八、带参数的类装饰器 九、装饰器的顺序 总结 写在后面 前言 最近有人问我装饰器是什么&#xff0c;我就跟他说&#xff…

偏微分方程数值解程序设计与实现——数学基础

常用算子符号 梯度算子 R d \mathbb{R}^d Rd空间中标量函数 u ( x ) u(\bf{x}) u(x)&#xff0c;其梯度算子定义如下&#xff1a; g r a d u ( x ) ∇ u ( x ) [ ∂ u ∂ x 0 ∂ u ∂ x 1 ⋮ ∂ u ∂ x d − 1 ] grad u(\mathbf{x})\nabla u(\mathbf{x}) \begin{bmatrix} …

偏微分方程的数值解(六): 偏微分方程的 pdetool 解法

偏微分方程的数值解系列博文&#xff1a; 偏微分方程的数值解(一):定解问题 & 差分解法 偏微分方程的数值解(二): 一维状态空间的偏微分方程的 MATLAB 解法 偏微分方程的数值解(三): 化工应用实例 ----------触煤反应装置内温度及转换率的分布 偏微分方程的数值解(四):…

微分方程数值解

一阶问题举例&#xff1a; 高阶问题举例 &#xff1a; 常微分方程数值解&#xff1a;向前欧拉方法之一阶问题 clc,clear,close all; a0;%初始时刻 b2*pi;%结束时刻 n100;%离散点数量 x00;%初值 h(b-a)/n;%步长 xx0 [0:n]*h;%离散点数组 funinline(sin(x)y,x,y); y01; %计算 y(…

常微分方程数值解法1

&#xff11;.牛顿迭代法 多数方程不存在求根公式&#xff0c;因此求精确根非常困难&#xff0c;甚至不可能&#xff0c;从而寻找方程的近似根就显得特别重要。牛顿迭代法使用函数 的泰勒级数的前面几项来寻找方程 的根。牛顿迭代法是求方程根的重要方法之一&#xff0c;其最大…

差分、偏微分方程的解法

这里写目录标题 微分方程数值求解——有限差分法matlab代码差分法的运用&#xff08;依旧是连续变量——>离散网格点&#xff09; PDE求解思路demo1demo2 微分方程数值求解——有限差分法 差分方法又称为有限差分方法或网格法&#xff0c;是求偏微分方程定解问题的数值解中…

微分方程数值解法(2)——椭圆型方程的有限差分法

此处参考教材为李荣华的《微分方程数值解法》 使用工具&#xff1a;Matlab 1. 算法&#xff1a;矩形网格上5点差分格式 2. 算法 I.需要求解的函数 function [v,vx,vy,f,aa,bb,cc,dd]u2D(x,y,ft)% ft为方程编号&#xff0c;u1D为精确解函数u&#xff08;t&#xff09;,注意与…

基础数学(8)——常微分方程数值解法

文章目录 期末考核方式基础知识解析解&#xff08;公式法&#xff09;解析解例题&#xff08;使用公式法&#xff0c;必考&#xff09;解析解的局限性 数值解数值解的基本流程 显示Euler法显示欧拉&#xff08;差值理解&#xff09;显示欧拉&#xff08;Taylor展开理解&#xf…

微分方程数值解法(1)——常微分方程初值问题的数值解法

此处参考教材为李荣华的《微分方程数值解法》 使用工具&#xff1a;Matlab 1. 算法 注: 最后一行应为k4,上面为笔误 2. 算法 I.需要求解的函数 function ff1D(t,u,ft)% ft为方程编号&#xff0c;u1D为精确解函数u(t),注意与f1D对应右端项函数f(t,u(t))switch ftcase 1 %P10…