穿什么有这么重要?——装饰模式

文章目录

  • 穿什么有这么重要?——装饰模式
    • 穿什么有这么重要?
    • 小菜扮靓第一版
    • 小菜扮靓第二版
    • 装饰模式
    • 小菜扮靓第三版
    • 商场收银程序再升级
    • 简单工厂+策略+装饰模式实现
    • 装饰模式总结

穿什么有这么重要?——装饰模式

穿什么有这么重要?

时间:3月16日20点  地点:大鸟房间  人物:小菜、大鸟

"大鸟,明天我要去见娇娇了,你说我穿什么去比较好?"小菜问大鸟道。

"这个你也来问我,干脆我代你去得了。"大鸟笑言。

“别开玩笑,我是诚心问你的。”

“哈哈,小菜呀,你别告诉我说四年大学你都没和女生约过会?”

"唉!谁叫我念的是理工科大学呢,学校里本来女生就少,所以这些稀有宝贝们,大一时早就被那些老手们主动出击搞定了,我们这些恋爱方面的小菜哪还有什么机会,一不小心就虚度了四年。"小菜突生伤感,叹气摇头,并小声地唱了起来,“不是我不小心,只是真情难以寻觅,不是我存心故意,只因无法找到良机……”

"喂!"大鸟打断了小菜,“差不多行了,感慨得没完没了。说正事,问我什么?”

“哦,你说我穿什么去见娇娇比较好?”

“那要看你想给人家什么印象?是比较年轻,还是比较干练;是比较颓废,还是要比较阳光;也有可能你想给人家一种极其难忘的印象,那穿法又大不一样了!”

“你这话怎么讲?”

“年轻,不妨走点Hip-Hop路线,大T恤、垮裤、球鞋,典型的年轻人装扮。”

“啊,这不是我喜欢的风格,我从来也没这样穿过。”

“那就换一种,所谓干练,就是要有外企高级白领的样,黑西装、黑领带、黑墨镜、黑皮鞋……”

“你这叫白领?我看是社会人。不行不行。”

“哈,来颓废的吧,颓废其实也是一种个性,可以吸引一些喜欢叛逆的女生。一般来说,其标志是:头发可养鸟、胡子能生虫、衬衣没纽扣、香烟加狐臭。”

“这根本就是’肮脏’的代表吗,开什么玩笑。你刚才提到给人家难忘印象,是什么样的穿法?”

“哈,这当然是绝妙的招了,如果你照我说的去做,娇娇想忘都难。”

“快说快说,是什么?”

“大红色披风下一身蓝色紧身衣,胸前一个大大的’S’,表明你其实穿的是’小号’,还有最重要的是,一定要’内裤外穿’……”

" 喂 , 你 拿 我 寻 开 心 呀 , 那 是 ’ 超 人 ’ 的 打 扮 呀 , ‘S’ 代 表 的 也 不是’Small’,是’Super’的意思。"小菜再次打断了大鸟,还是忍不住笑道,“我如果真的穿这样的服装去见MM,那可真是现场的人都终生难忘,而小菜我,社死现场,这辈子也不要见人了。”

"哈,你终于明白了!我其实想表达的意思就是,你完全可以随便一些,

平时穿什么,明天还是穿什么,男生嘛,只要干净一些就可以了,关键不在于你穿什么,而在于你人怎么样。对自己都这么没信心,如何追求女孩子?"

"哦,我可能是多虑了一些。"小菜点头道,“好吧,穿什么我自己再想想。没什么事了吧?那我回房了。”

"等等,"大鸟叫住了他,“今天的模式还没有开讲呢,怎么就跑了?”

“哦,我想着约会的事,把学习给忘了,今天学什么模式?”

小菜扮靓第一版

“先不谈模式,说说你刚才提到的穿衣问题。我现在要求你写一个可以给人搭配不同服饰的系统,比如类似QQ、电商平台或游戏都有的Avatar系统。你怎么开发?”

在这里插入图片描述

“你是说那种可以换各种各样的衣服裤子的个人形象系统?”

“是的,现在你就简单点,用控制台的程序,写可以给人搭配嘻哈服或白领装的代码。”

“哦,我试试看吧。”

半小时后,小菜的第一版代码出炉。

Person类:

在这里插入图片描述

客户端代码:

在这里插入图片描述

结果显示:

在这里插入图片描述

“哈,不错,功能是实现了。现在的问题就是如果我需要增加’超人’的装扮,你得如何做?”

"那就改改Person类就行了,"小菜说完就反应过来,“哦,不对,这就违背了开放-封闭原则了。哈,我知道了,应该把这些服饰都写成子类就好了。我去改。”

大鸟抬起手伸出食指对小菜点了点,“你呀,刚学的这么重要的原则,怎么还会忘?”

小菜扮靓第二版

过了不到十分钟,小菜的第二版代码出炉。

在这里插入图片描述

Person类:

在这里插入图片描述

服饰抽象类:

在这里插入图片描述

各种服饰子类:

在这里插入图片描述

注意上面都是继承Finery类,其余类类似,省略。

客户端代码:

在这里插入图片描述

结果显示同前例,略。

“这下你还能说我不面向对象吗?如果要加超人装扮,只要增加子类就可以了。”

“哼,用了继承,用了抽象类就算是用好了面向对象了吗?你现在的代码的确做到了’服饰’类与’人’类的分离,但其他问题还是存在的。”

“什么问题呢?”

“你仔细看看这段代码。”

在这里插入图片描述

"这样写意味着什么?"大鸟问道。

“就是把’大T恤’‘垮裤’'破球鞋’和’装扮的小菜’一个词一个词地显示出来呀。”

“说得好,我要的就是你这句话,这样写就好比:你光着身子,当着大家的面,先穿T恤,再穿裤子,再穿鞋,仿佛在跳穿衣舞。难道你穿衣服都是在众目睽睽下穿的吗?”

“你的意思是,应该在内部组装完毕,然后再显示出来?这好像是建造者模式呀。”

“不是的,建造者模式要求建造的过程必须是稳定的,而现在我们这个例子,建造过程是不稳定的,比如完全可以内穿西装,外套T恤,再加披风,打上领带,皮鞋外再穿上破球鞋;当然也完全可以只穿条裤衩就算完成。换句话就是说,通过服饰组合出一个有个性的人完全可以有无数种方案,并非固定的。”

“啊,你说得对,其实先后顺序也是有讲究的,如你所说,先穿内裤后穿外裤,这叫凡人,内裤穿到外裤外面,那就是超人了。”

“哈,很会举一反三嘛,那你说该如何办呢?”

“我们需要把所需的功能按正确的顺序串联起来进行控制,这好像很难办哦。”

“不懂就学,其实也没什么稀罕的,这可以用一个非常有意思的设计模式来实现。”

装饰模式

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

“啊,装饰这词真好,无论衣服、鞋子、领带、披风其实都可以理解为对人的装饰。”

“我们来看看它的结构。”

装饰模式(Decorator)结构图:

在这里插入图片描述

“Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职 责 。 Decorator , 装 饰 抽 象 类 , 继 承 了 Component , 从 外 类 来 扩 展Component类的功能,但对于Component来说,是无须知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能[DPE]。”

“来看看基本的代码实现。”

在这里插入图片描述

在这里插入图片描述

“我明白了,原来装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中[DPE]。用刚才的例子来说就是,我们完全可以先穿外裤,再穿内裤,而不一定要先内后外。”

在这里插入图片描述

"既然你明白了,还不快些把刚才的例子改成装饰模式的代码?"大鸟提醒道。

" 还 有 个 问 题 , 刚 才 写 的 那 个 例 子 中 ’ 人 ’ 类 是 Component 还 是ConcreteComponent呢?"

“哈,学习模式要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

“啊,原来如此。在这里我们就没有必要有Component类了,直接让服饰类Decorator继承人类ConcreteComponent即可。”

小菜扮靓第三版

二十分钟后,小菜第三版代码出炉。

代码结构图:

在这里插入图片描述

ICharacter接口(Component):

在这里插入图片描述

Person类(ConcreteComponent):

在这里插入图片描述

Finery类(Decorator):

在这里插入图片描述

具体服饰类(ConcreteDecorator):

在这里插入图片描述

其余类类似,省略。

客户端代码:

在这里插入图片描述

结果显示:

在这里插入图片描述

"如果我换一种装饰方式,比如说,增加草帽装扮,再重新组合一下服饰,应该如何做?"大鸟问道。

"那就增加一个草帽子类,再修改一下装饰方案就好了。"小菜开始写代码。

在这里插入图片描述

结果显示:

在这里插入图片描述

“哈,戴着草帽、光着膀子、打着领带、下身垮裤、左脚皮鞋、右脚球鞋的极具个性的小菜就展现在我们面前了。”

"你这家伙,又开始拿我开涮。我要这样,比扮超人还要丢人。"小菜抱怨道,“我在想,上一次说的策略模式,使用了商场收银软件,是否存在使用装饰模式的情况?

"好问题。事实上是有机会用的。比如说,我们商场10周年庆,要加大力度回馈客户,所有商品,在总价打8折的基础上,再满300返100,当然这只是一种销售方案,还可以是打7折,再满200送50,或者满300返50,再打7折,

也就是说,可以多种促销方案组合起来使用。我们的要求是最终实现的代码,影响面越小越好,也就是原来的代码能利用就要利用,改动尽量小一些。你可以考虑一下如何做。"

商场收银程序再升级

小菜:“我想想。我完全可以写个复杂的算法,先打8折,再满300返100,算法可以是下面这样。”

在这里插入图片描述

增加一个先折扣再返利的算法子类,初始化需要三个参数,并在计算时,先打折,再返利计算。

在这里插入图片描述

修改CashContext类,增加一个先打8折再满300返100的算法实例对象。

在这里插入图片描述

大鸟:“你这确实是达到了增加一种组合算法的功能实现,但你有没有发现,新类CashReturnRebate有原来的两个类:CashReturn和CashRebate有大量重复的代码?”

小菜:“是呀,我等于是把两个代码合并又写了一遍。”

大鸟:“另外,如果我现在希望增加一个先满300返100,再打折扣的算法,你如何修改呢?再写一个新类吗?如果我们再增加购买送积分、购买抽奖、购买送小礼品等算法,并且有了各种各样的先后组合,你打算怎么处理呢?”

小菜:“我……这个……”

大鸟:“哈哈,好好想想吧。装饰模式或许能帮到你。”

小菜:“我懂你意思了。看来我前面没有真的理解装饰模式。我再来试试。”

简单工厂+策略+装饰模式实现

小 菜 : " 无 须 增 加 CashReturnRebate 类 , 依 然 是 CashNormal 、CashReturn、CashRebate三种基本算法子类。增加一个接口ISale,用作装饰模式里的Component。"

在这里插入图片描述

大鸟:“你这样是可以实现同样的功能,但与装饰模式比较起来,并不完美。仔细对比观察一下,还有什么东西没有?”

小菜:“哦!我发现了,ConcreteComponent类不存在。那它应该是什么呢?”

大鸟:“装饰模式有一个重要的优点,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。我们现在的三个算法类,有没有最基础的呢?”

小 菜 : “CashNormal 是 最 基 础 的 。 哦 ! 我 知 道 了 , 是 把 它 作 为ConcreteComponent。我马上重构一下。”

在这里插入图片描述

CashSuper原来是抽象类,改成普通类,但实现ISale接口。

在这里插入图片描述

CashNormal,相当于ConcreteComponent,是最基本的功能实现,也就是单价×数量的原价算法。

在这里插入图片描述

另 外 两 个 CashSuper 的 子 类 算 法 , 都 在 计 算 后 , 再 增 加 一 个super.acceptCash(result, 1)返回。

在这里插入图片描述

重点在CashContext类,因为涉及组合算法,所以用装饰模式的方式进行包装,这里需要注意包装的顺序,先打折后满多少返多少,与先满多少返多少,再打折会得到完全不同的结果。

在这里插入图片描述

客户端算法不变:

在这里插入图片描述

结果显示:

在这里插入图片描述

单位1000元,数量为1的商品,原需支付1000元,如果选择先8折再满300送100算法的话,就是1000×0.8=800元,满足两个300元,返200元,最终结果是客户只需支付600元。

在这里插入图片描述

单位500元,数量为4的商品,原需支付2000元,如果选择先满200送50再7折算法的话,就是2000中有10个200,送10×50=500元,所以2000-500=1500元,再打7折,1500×0.7,最终结果是客户只需支付1050元。

大鸟:“非常棒!你完全实现了三个模式结合后的代码。现在的代码比刚才的想法好在哪里?”

小菜:“嗯!我也觉得很兴奋。现在无论如何组合算法,哪怕是先打折再返现,再打折再返现,我都只需要更改CashContext类就可以了。目前代码确实做到了开放封闭。设计模式真是好!”

装饰模式总结

“来来来,总结一下,你感觉装饰模式如何?”

“我觉得装饰模式是为已有功能动态地添加更多功能的一种方式。但到底什么时候用它呢?”

“答得很好,问的问题更加好。你起初的设计中,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,比如用西装或嘻哈服来装饰小菜,但这种做法的问题在于,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,就像你起初的那个’人’类,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了[DP]。所以就出现了上面那个例子的情况,我可以通过装饰,让你全副武装到牙齿,也可以让你只挂一丝到内裤。”

“就像你所说的,装饰模式的优点是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。像前面的原价算法就是最基础的类,而打折或返现,都算是装饰算法了。”

“是的,这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。我们不必去重复编写类似打折后再返现,或返现后再打折的代码,对于装饰模式来说,只是多几种组合而已。”

“这个模式真不错,我以后要记着常使用它。”

“你可要当心哦,装饰模式的装饰顺序很重要哦,比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若先加密了数据再用过滤功能就会出问题了,最理想的情况,是保证装饰类之间彼此独立,这样它们就可以以任意的顺序进行组合了。”

“是呀,穿上西装再套上T恤实在不是什么好穿法。”

"明天想好了要穿什么去见MM了吗?"大鸟突然问道。

“有了装饰模式,我还用得着担心我的穿着?再说,我信奉的是《天下无贼》中刘德华说的一句经典台词:‘开好车就是好人吗?’,小菜我魅力无限,不需装饰。”

大鸟惊奇地望着小菜,无法理解地说了句:“学完模式,判若两人,你够弓虽!”

如果对你有帮助,就一键三连呗(关注+点赞+收藏),我会持续更新更多干货~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1537994.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

手写redis实现分布式锁详细教程,满足可续锁、可重入等分布式锁条件

前言 本文将讨论的做一个高并发场景下避不开的话题,即redis分布式锁。比如在淘宝 的秒杀场景、热点新闻和热搜排行榜等。可见分布式锁是一个程序员面向高级的一门必修课,下面请跟着本篇文章好好学习。 redis分布式锁有哪些面试题 1.Redis做分布式的时…

执着追求与匠心独运 朵拉朵尚2024欧洲溯源 深入德国巴斯夫

执着追求与匠心独运 朵拉朵尚2024欧洲溯源 深入德国巴斯夫 前不久,朵拉朵尚踏上了其2024年欧洲溯源之旅的第三站—德国巴斯夫,一场旨在深化护肤智慧、共谋新品未来的深度交流盛宴在此拉开帷幕。作为全球最大的化工公司,巴斯夫不仅以其卓越的…

电脑录屏工具哪个好用?推荐新手几款实用工具介绍

现在不管是录个教学视频教教别人,还是直播游戏给粉丝看,或者是展示你的产品,都得用到它。但是市面上的录屏软件多得让人眼花缭乱,新手可能一看就懵了。别急,今天我就给你介绍几个特别好用的电脑录屏工具,不…

攻克大模型面试!RAG基础与应用痛点一网打尽!

RAG相关理论知识与经验整理。 谈到大模型在各垂直领域中的应用,一定离不开RAG,本系列开始分享一些RAG相关使用经验,可以帮助大家在效果不理想的时候找到方向排查或者优化。 本系列以医疗领域为例,用面试题的形式讲解RAG相关知识…

唤醒金融数据中台:我的数据驱动秘籍

目录 一、明析业务痛点和机会点二、数据驱动精准化营销三、一体化数据平台——整合金融数据1. 数据整合与标准化2. 数据服务与共享3.业务体系集中化 四、强化金融数据安全,筑牢数据保护防线 在当今数字化时代的大潮中,数据无疑是金融行业最耀眼的财富。作…

销售管理中的难题,你是否也深陷其中?

销售管理中的难题似乎总是让人头疼。从客户跟进不及时,到销售数据分析不足,再到团队沟通不畅,导致商机频频流失。销售目标总是难以达成,业绩压力越来越大,但解决方案却总是力不从心。面对这样的问题,你是不…

Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用增强版

前言 之前使用Chainlit集成LlamaIndex并使用通义千问大语言模型的API接口,实现一个基于文档文档的网页对话应用。 可以点击我的上一篇文章《Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用》 查看。 本次针对上一次的代码功能进一步的完善…

推动公平学习与身份归一化的视网膜神经疾病数据集

人工智能咨询培训老师叶梓 转载标明出处 在机器学习领域,公平性(也称为公正性或平等性)是一个日益受到关注的话题,它对于社会的福祉至关重要。然而,目前缺乏专门用于公平学习且包含成像数据的公共医学数据集&#xff…

分苹果 - 华为OD统一考试(E卷)

2024华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集 题目描述 A 和 B 两个人要分苹果。A 希望按照他的计算规则得到平均分配的苹果,而 B 希望在满足 A 的条件下获得尽可能多的苹果量。 A 的计算规则是按照二进制加法进行,并不计算进位。例如,12 + 5 =…

CAT1 DTU软硬件设计开源资料分析(TCP协议版本 )

一、CAT1 DTU方案简介: 远程终端单元DTU,一种针对通信距离较长和工业现场环境恶劣而设计的具有模块化结构的、特殊的计算机测控单元,它将末端检测仪表和执行机构与远程控制中心相连接。 奇迹TCP DTU版本DTU,用于将远程现场的传感…

VoIP协议

VoIP协议是VoIP业务的规范标准。我们都知道VoIP业务有着压倒性的优势。随着网络应用的多元化和低成本化发展,VoIP业务直接冲击着传统通信市场,那么目前VoIP协议目前常用的协议,如H.323、SIP、MEGACO和MGCP。 H.248 H.248是定义网关控制协议的ITU建议书…

分布式光伏发电站数据采集设备管理硬件解决方案

随着全球能源结构的转型和可再生能源的快速发展,光伏发电作为重要的清洁能源之一,在能源市场中占据了越来越重要的位置。AcrelCoud-1200分布式光伏运维云平台通过监测光伏站点的逆变器设备,气象设备以及摄像头设备,帮助用户管理分…

【Linux系统编程】第二十弹---进程优先级 命令行参数 环境变量

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、进程优先级 2.1、什么是优先级 2.2、优先级的描述 2.3、优先级与权限的关系 2.4、为什么要有优先级 2.5、Linux优先级的…

某oa命令执行漏洞挖掘思路

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

图像修复(Inpainting)技术的前沿模型与数据集资源汇总

图像修复(Image Inpainting)是一种计算机视觉技术,旨在填补图像中的缺失区域或去除图像中的不需要部分,使其看起来自然且无明显痕迹。其目标是根据图像的上下文信息和周围像素来推断和重建缺失区域的内容,以生成逼真且…

《机器学习》周志华-CH7(贝叶斯分类)

7.1贝叶斯决策论 对分类任务而言,在所有相关概率已知的理想情形下,贝叶斯决策论考虑如何基于这些概率核误判损失来选择最优的类别标记。 R ( x i ∣ x ) ∑ j 1 N λ i j P ( c j ∣ x ) \begin{equation} R(x_{i}|x)\sum_{j1}^{N}\lambda_{ij}P(c_{j}…

DTMF2str集成工具

DTMF2str 项目地址: baicaiyihao/DTMF2str: DTMF解码并转换为字符串 (github.com) 用于CTF中misc DTMF题中,方便ctfer解题。 注:工具根据现有的一些题型进行编写的,如果有无法解出的题型可以提issus后续进行完善。 工具功能&a…

C++独立开发开源大数计算库 CBigNum

项目简介&项目地址 CBigNum 是本人独立开发开源的一款大数计算库,支持任意位数整数带任意位数小数的浮点运算。您可以通过本库执行非常大的数据运算或非常高精度的除法运算(您可以随意指定除法的小数保留到第几位)。 项目地址:https://github.com/…

MATLAB路径规划如何采用矢量法让他们尽量在一个方向??

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收…

HTML | 外部引入 CSS 的2种方式:link和@import有什么区别?

外部引入 CSS 有2种方式,link 和 import。就结论而言,强烈建议使用 link ,慎用 import 方式。 两者都是外部引用 CSS 的方式,但是存在一定的区别: (1)从属关系区别 link是HTML / XHTML标签&a…