装饰模式

简介: 主要内容有:该模式的介绍,包括:引子、意图(大白话解释)类图、时序图(理论规范)该模式的代码示例:熟悉该模式的代码长什么样子该模式的优缺点:模式不是万金油,不可以滥用模式该模式的实际使用案例:了解它在哪些重要的源码中被使用


前言



主要内容有:

  • 该模式的介绍,包括:
  • 引子、意图(大白话解释)
  • 类图、时序图(理论规范)
  • 该模式的代码示例:熟悉该模式的代码长什么样子
  • 该模式的优缺点:模式不是万金油,不可以滥用模式
  • 该模式的实际使用案例:了解它在哪些重要的源码中被使用


结构型——装饰器模式 Decorator Patter



引子

当你需要统计一个方法的运行时间时,你会怎么做?是不是下面这种方法呢,用两个时间语句统计出耗时?

public static void main(String[] args){
    long start = System.currentTimeMillis();
    algo(); // 执行代码块
    long end = System.currentTimeMillis();
    System.out.println(end - start);
}
复制代码

如果使用了装饰器模式,你可以将统计时间的方法独立出来,变成方法上面的@Timer:

public class Foo {
    @Timer
    public void algo1() {
        ArrayList<Integer> l = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            l.add(1);
        }
    }
}
复制代码

这样你就可以在不插入任何语句在原方法的情况下,统计原方法的执行时间,就像在原方法外面披了一层皮一样,这就是装饰器!

PS:如果你了解Python,那么你可能会经常使用到装饰器。在Java中,使用起来有一些复杂,但也是完全能够通过注解做到的,它可以同样应用在权限控制、日志、缓存等方面,方便的对代码进行解耦,让通用的功能“切入”原先的代码,使得开发时可以更专注于业务逻辑。


定义

装饰模式动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。

其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。


类图

如果看不懂UML类图,可以先粗略浏览下该图,想深入了解的话,可以继续谷歌,深入学习:

装饰模式包含如下角色:

  • Component: 抽象构件
  • ConcreteComponent: 具体构件
  • Decorator: 抽象装饰类
  • ConcreteDecorator: 具体装饰类


时序图

时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。时序图中显示的是参与交互的对象及其对象之间消息交互的顺序。

我们可以大致浏览下时序图,如果感兴趣的小伙伴可以去深究一下:


代码实现

还记得引子中举得例子吗?

我们现在Python下看看如何实现这个统计方法执行时间的函数

首先,我们定义一个函数,如下:

def exe_time(func):
  def new_func(*args, **args2):
    t0 = time.time()
    print "@%s, {%s} start" % (time.strftime("%X", time.localtime()), func.__name__)
    back = func(*args, **args2)
    print "@%s, {%s} end" % (time.strftime("%X", time.localtime()), func.__name__)
    print "@%.3fs taken for {%s}" % (time.time() - t0, func.__name__)
    return back
  return new_func
复制代码

接下来,我们就可以在需要计时的函数前一行引用它作为装饰,比如:

@exe_time
def foo():
  for i in xrange(10000000):
    pass
复制代码

输出效果如下:

@13:12:27, {foo} start
@13:12:27, {foo} end
@0.203s taken for {foo}
复制代码

在Java中,没有Python这种天秀的语法糖,我们需要用注解实现,已经有网友写的例子,这里就不班门弄斧了。


使用场景举例


Spring

spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。


JDK源码中的使用

  • java.io.BufferedInputStream(InputStream)
InputStream inputStream = new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
};
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//增强了原本InputStream的功能
复制代码
  • java.io.DataInputStream(InputStream)
  • java.io.BufferedOutputStream(OutputStream)
  • java.util.zip.ZipOutputStream(OutputStream)
  • java.util.Collections#checkedList|Map|Set|SortedSet|SortedMap


优缺点

优点

  • 装饰模式与继承本质其其实都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  • 可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

缺点

  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。


补充:装饰模式与代理模式的区别

两者都是对类的方法进行扩展,但装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上 使用增强后的功能。增强后你还是你,只不过能力更强了而已;而代理模式则强调要让别人帮你去做一 些本身与你业务没有太多关系的职责(记录日志、设置缓存)。代理模式是为了实现对象的控制,因为 被代理的对象往往难以直接获得或者是其内部不想暴露出来。


参考



相关文章
|
7月前
|
监控 BI C++
Quick BI使用案例14:基于本月时间进度的月度目标达成分析
本文以中大型企业“月度滚动目标管理”为背景,详解如何用Quick BI自动计算本月总天数、今日序号及时间进度,实现预算消耗与时间进度的智能匹配监控,助力数据驱动精细化运营。
|
3月前
|
人工智能 关系型数据库 MySQL
给你的AI Agent装上"行为记忆":agentmemory安装到整合全指南
agentmemory是专为AI Agent设计的本地化“情节记忆”引擎,解决其无状态、易失忆问题。它自动记录操作历史、决策与教训,支持LLM压缩、向量检索与知识图谱,R@5召回率达95.2%,节省92% token,开源(Apache 2.0),零外部依赖,15分钟即可部署启用。
1227 0
|
4月前
|
存储 运维 监控
阿里云无影云电脑完整使用指南:从账号开通到配置、接入、管理与运维全流程
阿里云无影云电脑是一种基于云计算的虚拟桌面服务,用户可以通过网络访问位于云端的完整桌面环境,包括操作系统、应用程序、文件资源和网络能力。与传统本地电脑不同,云电脑的计算、存储和管理主要集中在云端,终端设备更多承担输入、输出和展示角色。
826 1
|
10月前
|
存储 安全 数据管理
没听过冷数据?一文带你读懂冷数据
冷数据指长期不用但需合规保存的历史数据,如旧订单、合同等。它虽不常用,却关乎成本、安全与合规。管理不当将导致存储浪费、系统变慢、审计风险。应通过分类、分级存储、自动归档与索引管理,确保“用时能查”,实现数据治理的精细化与可持续化。
|
5月前
|
网络协议 安全 API
IP风险识别为什么比传统黑名单更靠谱?用IP离线库实现动态画像三大优势
某电商平台黑名单拦截率仅37%,黑产靠住宅代理与动态IP轻松绕过。IP动态画像以网络类型、代理特征、风险评分三维度,实现毫秒级(0.35ms)、高精度(92%识别率)、可解释的主动防御,彻底告别“事后封禁”。
IP风险识别为什么比传统黑名单更靠谱?用IP离线库实现动态画像三大优势
|
4月前
|
存储 人工智能 弹性计算
2026年阿里云618大促「AI加速季,智惠生产力」活动详解
2026年阿里云以「AI加速季,智惠生产力」为主题开启618年度大促,活动周期锁定6月1日至6月30日,整月全周期开放各类限时秒杀、长效特惠、企业算力补贴、新人券包、AI产品专项优惠,覆盖轻量应用服务器、ECS云主机、GPU算力、云数据库、存储CD、建站服务全品类。依托官方5亿元专项算力补贴加持,新用户入门机型低至38元/年,新老通用ECS经济型机型99元/年起,企业专属u1实例199元/年,叠加满减券、迁补贴后综合折扣低至0.8折。本文结合官方活动规则、机型定价、全渠道参与入口、优惠叠加逻辑、实操部署脚本、避坑要点全方位拆解,帮助个人站长、开发者、中小微企业低成本选购适配云资源,全文从活动周
1250 0
|
11月前
|
运维 监控 Devops
运维不是“救火队”:聊聊运维团队的组织、管理与成长之道
运维不是“救火队”:聊聊运维团队的组织、管理与成长之道
718 5
|
8月前
|
搜索推荐 数据挖掘 测试技术
LLM推理时计算技术详解:四种提升大模型推理能力的方法
2025年LLM发展新趋势:不卷训练,专攻推理!本文详解四大推理时计算技术——Chain-of-Thought(深度)、Self-Consistency(宽度)、Tree-of-Thoughts(搜索)、Reflexion/Self-Refine(迭代),配可运行代码与实战对比,助你在不重训模型前提下显著提升性能。
846 0
LLM推理时计算技术详解:四种提升大模型推理能力的方法
|
7月前
|
人工智能 Ubuntu 网络安全
0基础1分钟部署OpenClaw(Clawdbot)指南,1699+ OpenClaw Skills生态与实操应用解析
OpenClaw(原Clawdbot、Moltbot)作为2026年AI自动化领域的核心工具,凭借“自然语言指令+任务自动执行”的核心能力,突破了传统对话式AI的局限。其真正的价值核心在于OpenClaw Skills(技能插件)生态——这套插件系统如同为AI大脑配备了“灵活双手”,让智能体从“只会说”升级为“会做事”,覆盖办公自动化、开发辅助、生活服务等31个主要分类,截至2026年2月已拥有1715+个社区贡献技能,且持续高速增长。
1151 4
|
搜索推荐 数据安全/隐私保护 UED
装机必备:Everything 绿色免安装版,快速定位文件极速文件搜索,快速定位文件,文件管理搜索
Everything是一款高效实用的文件搜索工具,以其快速、精准的搜索能力著称。它支持实时搜索本地和远程文件,提供多种过滤器与排序功能,界面简洁友好,资源占用低。最新版本新增拼音搜索、全文检索、智能推荐等功能,同时优化了多语言支持、安全性和隐私保护,极大提升了用户体验,是管理海量文件的绝佳选择。
1468 5

热门文章

最新文章