设计模式 - 装饰者模式,就该这样学!

【23种设计模式】装饰器模式 使用组合替代继承,对原生对象的方法做增强,增加新的行为和能力。 装饰器设计模式(Decorator)是一种结构型设计模式,它允许动态地为对象添加新的行为。它通过创建一个包装器来实现,即将对象放入一个装饰器类中,再将装饰器类放入另一个装饰器类中,以此类推,形成一条包装链。 在不改变原有对象的情况下,动态地添加新的行为或修改原有行为。 阅读详情

目录

一、结构型模式

1.1、装饰者模式

1.1.1、概念

1.1.2、案例实现1

1.1.3、案例实现2

1.1.4、优缺点

1.1.5、使用场景


一、结构型模式


1.1、装饰者模式

1.1.1、概念

装饰者模式就是指在不改变现有对象结构的情况下,动态的给该对象增加一些职责(增加额外功能)的模式.

例如,在一个博客系统中,有时候你希望对方关注你后才能查看你的文章,或者是对方因为你的文章充值了 vip 后才可以查看你的文章,那么此时就可以使用装饰者模式,通过判断用户的权限,动态的给文章增加职责.

装饰者模式中的角色如下:

  • 抽象组件:定义一个抽象接口用来规范附加的对象.
  • 具体组件:实现抽象构件,将来会被添加一些职责).
  • 抽象装饰者:继承抽象构件 和 持有抽象构件的引用,可以通过 子类 扩展具体的构件.
  • 具体装饰者:继承抽象装饰,重写相关方法,给具体的构件对象添加附加责任.

1.1.2、案例实现1

需求:实现一个咖啡商店系统,咖啡可以动态的加糖加奶.

//抽象组件
interface Coffee {

    fun getDesc(): String
    fun getCost(): Double

}

//具体组件
class SimpleCoffee: Coffee {

    override fun getDesc(): String = "[ simple coffee ]"
    override fun getCost(): Double = 6.0

}

//抽象装饰者
abstract class CoffeeDecorator(
    private val coffee: Coffee
): Coffee {

    override fun getDesc(): String = coffee.getDesc()
    override fun getCost(): Double = coffee.getCost()

}

//具体装饰者
class MikeDecorator(
    coffee: Coffee
): CoffeeDecorator(coffee) {

    override fun getDesc(): String = "${coffee.getDesc()}, mike"
    override fun getCost(): Double = coffee.getCost() + 2.0

}

//具体装饰者
class SugarDecorator(
    coffee: Coffee
): CoffeeDecorator(coffee) {

    override fun getDesc(): String = "${coffee.getDesc()}, sugar"
    override fun getCost(): Double = coffee.getCost() + 1.0

}

fun main() {
    val simpleCoffee = SimpleCoffee()
    println("simpleCoffee:")
    println("desc: ${simpleCoffee.getDesc()}")
    println("cost: ${simpleCoffee.getCost()}")

    //加奶
    val mikeSimpleCoffee = MikeDecorator(simpleCoffee)
    println("mikeSimpleCoffee:")
    println("desc: ${mikeSimpleCoffee.getDesc()}")
    println("cost: ${mikeSimpleCoffee.getCost()}")

    //加糖
    val mikeSugarSimpleCoffee = SugarDecorator(mikeSimpleCoffee)
    println("mikeSugarSimpleCoffee:")
    println("desc: ${mikeSugarSimpleCoffee.getDesc()}")
    println("cost: ${mikeSugarSimpleCoffee.getCost()}")

}


执行结果如下:

1.1.3、案例实现2

a)BlogShow 接口定义了一个博客展示的基础功能,BaseBlogShow 进行了实现.

//抽象构建角色
interface BlogShow {

    fun getTitle(): String
    fun getContent(): String
    fun display()

}

//具体构建角色
data class BaseBlogShow(
    private val title: String,
    private val content: String
): BlogShow {

    override fun getTitle() = title

    override fun getContent() = content

    override fun display() {
        println("title: $title")
        println("content: $content")
    }

}

b)BlogShowDecorator 是抽象装饰者,定义了规范,并且持有 blogShow 对象(抽象构建对象).

FollowDecorator 和 VipDecorator 是具体装饰者,将来 BaseBlogShow 对象要进行动态扩展的时候,就可以将 BaseBlogShow 对象作为 具体装饰者的构造参数,动态扩展.

//抽象装饰角色
abstract class BlogShowDecorator(
    protected val blogShow: BlogShow
): BlogShow {

    override fun getTitle() = blogShow.getTitle()
    override fun getContent() = blogShow.getContent()
    override fun display() = blogShow.display()

}

//具体装饰角色
class FollowDecorator(
    blogShow: BlogShow
): BlogShowDecorator(blogShow) {

    override fun display() {
        val title = super.getTitle()
        val content = if(super.getContent().length > 60)
            super.getContent().substring(0, 60).plus("...")
        else
            super.getContent()

        println("title: $title")
        println("content: $content")
        println("> 关注作者,查看更多内容!")
    }

}

//具体装饰角色
class VipDecorator(
    blogShow: BlogShow
): BlogShowDecorator(blogShow) {

    override fun display() {
        val title = super.getTitle()
        val content = if(super.getContent().length > 60)
           super.getContent().substring(0, 60).plus("...")
        else
           super.getContent()

        println("title: $title")
        println("content: $content")
        println("> 充值 vip,查看更多内容!")
    }

}

c)使用如下

fun main() {
    //假设从数据库中拿到数据
    val dbBlog = BaseBlogShow("Kotlin (programming language)", "Kotlin is a cross-platform, statically typed, general-purpose high-level programming language with type inference. Kotlin is designed to interoperate fully")
    //这里根据用户的权限来给文章进行不同的内容
    //...
    //假设用户未关注对方,但是对方的文章设置了关注才能访问
    //那么此处添加 "关注装饰器"
    var blog = FollowDecorator(dbBlog)
    //最后给该用户展示
    blog.display()
}

运行结果如下 

1.1.4、优缺点

优点:

动态扩展:比继承具有更好的扩展性(继承时静态附加责任,装饰者时动态添加责任),可以在不修改原类的情况下,给对象添加责任.

缺点:

增加系统复杂度:装饰者比继承使用的类可能会少,但比继承使用的对象可能更多,更多的对象在程序排查错误的时候可能更复杂.

1.1.5、使用场景

1. 当不能采用继承的方式对程序进行扩展,比如存在大量的独立扩展,为了支持每一种组合产生大量子类,导致子类数目爆炸增长、或者是 类定位为 final 类型(不能继承).

2. 在不影响其他类的情况下,以动态的方式添加责任.

QGIS|如何将WGS84转换为CGCS 2000坐标系? QGIS 3中如何将WGS84转换为国家2000大地坐标系? 今天来回答一位朋友在后台留言提出的问题:怎么将WGS84坐标转换为国家2000大地坐标系。 01工程坐标系 从地图窗口右下角的状态栏可以看到当前地图窗口的坐标系,即工程坐标系(Project CRS)。当前地图可以由多个图层组成,各种来源数据的坐标参照系(Layer CRS)并不一定相同,QGIS在绘制图层之前将根据工程坐标系进行动态坐标转换,然后显示在地图画布中。 因此,在处理空间数据的过程中,一定要特别注意... 阅读详情

相关推荐

GAMES101作业3-遇到的各种问题及解决方法

记录在做作业3时遇到的一些坑!以及最后的解决办法。

qq_41835314的博客 6815

装饰器模式(Decorator Pattern)

装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

FH的博客 998

NVIDIA GPU任务调度全景:从Block分配到Warp发射

GPU并行计算的核心是任务调度,而CUDA kernel在GPU上的执行并非简单的一次性操作,而是经过从CPU命令队列到硬件前端,再到GigaThread引擎和Warp Scheduler的多层协同。理解这一过程,是性能优化的基础。Warp作为硬件调度的基本单位,其状态切换与延迟隐藏能力直接决定计算单元的利用率;而Occupancy作为衡量SM上活跃Warp池大小的指标,也并非越高越好,需要结合访存模式与资源占用综合判断。对于多任务并发场景,Stream优先级、计算抢占、MIG硬件隔离与MPS软件共享等机制

weixin_32612263的博客 267

设计模式第7讲——装饰者模式(Decorator)

装饰者模式是一种结构型设计模式。一、什么是装饰者模式 二、角色组成 三、优缺点 四、应用场景 4.1 应用实例 4.2 java实例 五、代码实现5.0 UML类图5.1 Hero(英雄-抽象组件)5.2 BlindMonk(盲僧-具体构件)5.3 SkillDecorator(技能装饰-抽象装饰器)5.4 QDecorator(Q技能-具体装饰器)5.5 WDecorator(W技能-具体装饰器)5.6 EDecorator(E技能-具体装饰器)5.7

让~学习~成为一种习惯(橡 皮 人の技术博客) 6797

如何加载交易策略EA到MT4/MT5

1、打开MT4/MT5软件 2、首先,必须有一个EA,而且必须是mq4/ex4为扩展名。点击左上角“文件”—“打开数据文件夹”,找到安装路径 3、将EA的ex4或mq4文件放到MT4目录\MQL4\Experts里面(本文以名为Demo的EA为例) 4、如果有DLL库文件,复制到experts目录下的libraries子目录中 5、如果有tpl模板文件,复制到templates目录中 6、添加完成后重启MT4,点击允许EA运行图标 7、在导航中找到刚才安装的EA,拖拽到...

weixin_41364817的博客 7358

数据结构实验1.2—高精度计算PI值(西工大)

这是数据结构第二题的题目,是让我们根据用户的需求来计算派的值 这是题目的详细描述,刚看到这道题的时候,我是真的头大,完全没有思路,于是查找了一些大佬的笔记后才开始编写 这是我在写这些代码是所运用到的数学反三角函数幂次展开式的知识。 下面是正确的代码以及我的一些见解,和需要注意的一些地方。希望能对你有所帮助。如有更加精简的算法,请在评论区留下你的算法!!!谢谢!!! #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdl

abcdef0623的博客 5831

23种设计模式——装饰者模式

文章目录23种设计模式——装饰者模式1、装饰者模式概述2、装饰者模式的结构3、装饰者模式的实现4、装饰者模式的应用场景 23种设计模式——装饰者模式 1、装饰者模式概述 背景 有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。 装饰者模式的定义 装饰者(Decorator)模式的定义:指在不改

万里顾一程的博客 5291

动态时间规整(Dynamic Time Warping,DTW):让时间序列分析不再枯燥和代码全分析

动态时间规整(DTW)是一种用于比较时间序列相似性的算法,特别适用于处理长度不同或时间轴不对齐的序列。本文介绍了DTW的核心概念,包括其通过非线性对齐解决时间扭曲问题的能力,以及在语音识别、金融分析等领域的应用。通过Python代码示例,演示了如何计算两个模拟时间序列的DTW距离,并可视化最优对齐路径。结果显示,DTW能够有效捕捉序列间的相似模式,即使它们在时间轴上存在偏移或伸缩。该算法通过最小化累积距离来评估相似性,得分越低表明序列间相似度越高。

此星光明博客 160

设计模式之【装饰者模式】,实现“穿衣打扮”自由原来这么简单

装饰者模式(Decorator Pattern),也称为包装模式(Wrapper Pattern)、装饰器模式,是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。在 GoF 的《设计模式》一书中,对装饰者模式是这样理解的:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式相比生成子类更灵活。装饰者模式的核心是扩展功能。使用装饰者模式可以透明且动态地扩展类的功能。装饰器模式主要解决。

秃了也弱了 2330

Google antigravity 不支持你所在地区?手把手教你把账号改成支持地区

Google antigravity功能火爆,但国内老账号根本用不了🤬本文分享几种有效的账号国家地区切换方法,最快几分钟就能让antigravity直接亮起🔥

XiaoqiangClub的博客 2万+

【RT-DETR涨点改进】独家小目标涨点改进篇 | TGRS 2025 | RT-DETR引入ABRNet小目标检测顶刊中的:ARF自适应性感受野和MCA双向交叉轴注意力,适合小目标检测有效涨点

本文提出了一种改进的RT-DETR小目标检测方法,通过集成自适应感受野模块(ARF)和多尺度交叉轴注意力模块(BC)来提升检测性能。ARF模块采用多种卷积核动态调整感受野,有效捕获多尺度目标特征并减少背景干扰;BC模块通过多尺度交叉轴注意力机制增强全局信息提取和特征融合能力。实验表明,该方法在复杂背景下显著提升了红外小目标检测的精度和效率,同时降低了计算开销。文章详细介绍了模块结构、原理及实现代码,并提供了多种改进配置方案,为小目标检测任务提供了有效的解决方案。

Ai缝合怪、助力小伙伴高效发论文 570

设计模式-装饰者模式(Decorator)

装饰者模式(Decorator Pattern)是一种结构型设计模式,它的定义是在不改变原有对象结构的基础上,动态地给该对象增加一些职责(即增加其额外功能)。这种模式允许向一个现有的对象添加新的功能,同时又不改变其结构。它是继承的一种替代方案,可以实现在运行时动态地扩展对象的行为,而无需修改原有代码。

m0_51176516的博客 2109

【Zephyr驱动专题】01_深扒MPU6050陀螺仪寄存器

MPU6050作为最常用的6轴运动跟踪器件,其寄存器配置直接影响传感器性能和功能实现。本文将深入解析关键寄存器,并使用逻辑分析仪抓取信号进行分析。

zero的博客 1571

(八)趣学设计模式 之 装饰器模式!

装饰器模式就像给对象穿衣服,让它拥有不同的功能!

qq_56158663的博客 1485

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

『设计模式』小伙你的穿搭很潮!--装饰者模式

装饰模式(Decorator):又名包装模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。 装饰模式常常被称为包裹模式,就是因为每一个具体装饰类都将下一个具体装饰类或者具体构成类包裹起来。 包含角色 抽象构成(Component)角色 给出一个抽象接口,以规范准备接收附加责任的对象。 具体构成(Concrete Component)角色 实现组件对象接口,通常就是被装饰器装饰的对象。 装饰(Decorator)角色 持有一个构件(Component)对象的实例,并定义一个与抽象.

日拱一卒,功不唐捐 8048

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C++设计模式04-——装饰设计模式

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。——— 百度百科主体(被装饰者)饰品(装饰)比如:定做的奶油蛋糕,蛋糕是主体,而蛋糕的外包装、丝带、花朵都是饰品。在某些情况下我们可能会"过度地使用继承来扩展对象的功能",由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。...

qq_51340322的博客 1776

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

设计模式Python版 装饰模式

介绍了GOF设计模式中的装饰模式,用Python实现装饰模式的示例,以及装饰模式在Django中的应用。

分享、交流、合作 1284

装饰器设计模式

装饰器设计模式(Decorator)是一种结构型设计模式,它允许动态地为对象添加新的行为。它通过创建一个包装器来实现,先将对象放入一个装饰器类中,再将装饰器类放入另一个装饰器类中,以此类推,形成一条包装链。这样可以在不改变原有对象的情况下,动态地添加新的行为或修改原有行为。在 Java 中,实现装饰器设计模式的步骤如下:(1)定义一个接口或抽象类,作为被装饰对象的基类(2)定义一个具体的被装饰对象,实现基类中的方法(3)定义一个抽象装饰器类,继承基类,并将被装饰对象作为属性。

学习技术的路上不断沉淀自己 1281

【详解设计模式】-装饰者模式,换个马甲我也认识你!

什么是装饰者模式 装饰者模式是GOF23中设计模式之一,属于结构型模式。 通过这种设计模式,能够动态地给一个对象添加额外的能力,同时又不改变原有对象的结构。 动态地给一个类添加额外的功能,我们想到了Java中的继承机制,通过扩展父类的方式,可以让子类拥有一些额外的功能。使用装饰者模式,同样能达到这种效果,而且不用继承,使用起来更加灵活便利。 装饰者模式代码实现 我们创建一个手机接口IPhone和实...

Java成魔之路 876

装饰者设计模式

装饰者设计模式 课程大纲 一、 继承带来的问题 1、 话说威哥当年创业:卖豆浆,因为豆浆纯,分店几乎开遍了县城的所有的村,由于发展实在是太块了,所以急于由计算机实现一套自动记账系统。 2、 主料:豆浆,配料:糖,黑豆,五谷,鸡蛋。 4、 这就是所谓的“类爆炸“。 二、 装饰者设计模式概述 1、 意图:动态的给一个对象添加有些额外的职责,就增加功能来说,Decorator模式

咸蛋超人 2786

JS设计模式——装饰器模式

什么是装饰者模式? 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 实例 拿最近比较火的吃鸡游戏(绝地求生:大逃杀PUBG)来说,游戏中每个玩家降落到岛上,刚开始是一无所有的,需要通过捡拾或掠夺装备来武装自己,然后经过互相残酷的拼杀,获得游戏的胜利。 游戏过程中,我们可以把每一个玩...

userkang的博客 1913

【设计模式】装饰者模式?点过奶茶你就知道!

【设计模式】装饰器模式 继承滥用是一个问题,我们如何使用对象组合的方式,来实现运行时装饰类。熟悉装饰器模式,可以在不修改底层代码的情况下,对对象赋予新的内容。 1 场景 1.1 需求描述 奶茶店现在逐步都支持了线上点餐的方式,我们现在的目标就是实现一个简单的奶茶选择搭配生成对应搭配的类型选择结果与价格的一个功能。 我们都知道点一杯奶茶的使用的订单系统,基本如下: (1)选择奶茶类型例如:乌龙奶茶(Wulong)、抹茶奶茶(Mocha)、可可奶茶(Keke)、招牌芋圆奶茶(yuyuan)。 点击图片之后进入选

路遥知码力的博客 1256

设计模式之装饰者模式-有时候还是需要装饰一下自己才好!

一、装饰者模式的概念 装饰者模式又叫做包装模式,在不必改变原有类文件的情况下,它通过创建一个包装对象来不断地装饰原来的对象,来动态地扩展对象的功能,是继承关系的一个替换方案。 二、装饰者模式使用场景 1、当需要给一个对象扩展新的功能或者添加新的职责时可以使用装饰者模式。 2、当需要给一个对象动态的添加或者撤销功能时可以使用装饰者模式。 3、当一个类需要大量扩展时或者使用继承关系比较困难时,可以使用...

ISmileLi的博客 340

代理设计模式与装饰设计模式的对比

写上一篇文章的时候查了一下相关的资料,结果突然发现对于代理设计模式与装饰设计模式有点混淆,百度搜索的结果也不是很明确,都是说代理设计模式重在对与代理对象的控制,而装饰设计模式重在对装饰对象的增强,其实这么说没有什么问题,但是稍微抽象了一些,为了便于理解,我们可以分别写一下来对比看看。 其实在代理设计模式里比较容易跟装饰设计模式混淆的是静态代理,两个都是在被代理或者装饰的对象外面套了一层,然后自己实现方法的时候调用成员变量的方法举一个例子来说明一下:比如在一个异次元的古代,碰巧是封建帝制,大臣向皇帝呈折子的时

cswhit的博客 366

设计模式 - 装饰者模式 Java&Kotlin

同算法与数据结构一样,设计模式同样是作为一个优秀程序员必须熟练掌握与应用的基本功,在阅读源码或者优秀的开源项目的同时,不难发现各种设计模式的灵活运用,叹为观止。 接下来一系列博客,将和大家一起分享这些常用的设计模式。 观察者模式 装饰者模式 工厂模式 单例模式 建造者模式​​​​​​​ 本篇一起来看看装饰者模式是如何工作的,装饰者模式的概念,直接看起来个人认为是比较难以理解与应用的,...

sinat_33150417的博客 408

装饰类设计模式

装饰类是什么概念呢?如果已有的对象的功能不够优化,我们就可以定义类,将已有的对象传入,基于已有的功能,并提供加强的功能。那么该类就成为装饰类。装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰的对象的功能来通过加强功能。首先我们先来看一个例子: //早期的人的吃饭方式 class Person{ public void chifan(){ System.out.println("吃饭"

anyway1919的博客 1921
上一篇: 设计模式 - 适配器模式,就该这样学!
下一篇: 设计模式 - 模板方法模式,就该这样学!
陈亦康
陈亦康 优质创作者: Java技术领域 优质创作者: Java技术领域
博客等级 码龄5年 6万+粉丝 388原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈亦康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值