【23种设计模式】装饰模式(九)

2023-09-12 09:46:00

前言

装饰模式,英文名称:Decorator Pattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理解吧,大家一定要看清楚,是“装修”,不是“装饰”。在房子装修的过程中,各种功能可以相互组合,来增加房子的功用。类似的,如果我们在软件系统中,要给某个类型或者对象增加功能,如果使用“继承”的方案来写代码,就会出现子类暴涨的情况。比如:IMarbleStyle是大理石风格的一个功能,IKeepWarm是保温的一个接口定义,IHouseSecurity是房子安全的一个接口,就三个接口来说,House是我们房子,我们的房子要什么功能就实现什么接口,如果房子要的是复合功能,接口不同的组合就有不同的结果,这样就导致我们子类膨胀严重,如果需要在增加功能,子类会成指数增长。

装饰模式的定义

上述的问题的根源在于我们“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,所谓静态特质,就是说如果想要某种功能,我们必须在编译的时候就要定义这个类,这也是强类型语言的特点。静态,就是指在编译的时候要确定的东西;动态,是指运行时确定的东西。使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。如何使“对象功能的扩展”能够根据需要来动态(即运行时)地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低?装饰者模式解决此问题应运而生,动态地给一个对象增加一些额外的职责。

装饰模式的组成

  • 抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象。

  • 具体构件角色(Concrete Component):定义一个将要接收附加责任的类。

  • 装饰角色(Decorator):持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。

  • 具体装饰角色(Concrete Decorator):负责给构件对象添加上附加的责任。image

装饰模式的实现

以装修房子为例,完成装饰着模式的代码实现

房子定义
/// <summary>
    /// 该抽象类就是房子抽象接口的定义,该类型就相当于是Component类型,是饺子馅,需要装饰的,需要包装的
    /// </summary>
    public abstract class House
    {
        /// <summary>
        /// 房子的装修方法--该操作相当于Component类型的Operation方法
        /// </summary>
        public abstract void Renovation();
    }
   /// <summary>
    /// MyHouse的房子,我要按我的要求做房子,相当于ConcreteComponent类型
    /// </summary>
    public sealed class MyHouse : House
    {
        public override void Renovation()
        {
            Console.WriteLine("装修我的房子");
        }
    }
装饰类的定义
/// <summary>
    /// 该抽象类就是装饰接口的定义,该类型就相当于是Decorator类型,如果需要具体的功能,可以子类化该类型
    /// </summary>
    public abstract class DecorationStrategy : House //关键点之二,体现关系为Is-a,有了这个关系,装饰的类也可以继续装饰了
    {
        //通过组合方式引用Decorator类型,该类型实施具体功能的增加
        //这是关键点之一,包含关系,体现为Has-a
        protected House _house;

        //通过构造器注入,初始化平台实现
        protected DecorationStrategy(House house)
        {
            this._house = house;
        }

        //该方法就相当于Decorator类型的Operation方法
        public override void Renovation()
        {
            if (this._house != null)
            {
                this._house.Renovation();
            }
        }
    }
安全需求类装饰定义
/// <summary>
    /// 具有安全功能的设备,可以提供监视和报警功能,相当于ConcreteDecoratorA类型
    /// </summary>
    public sealed class HouseSecurityDecorator : DecorationStrategy
    {
        public HouseSecurityDecorator(House house) : base(house) { }

        public override void Renovation()
        {
            base.Renovation();
            Console.WriteLine("增加安全系统");
        }
    }
保暖需求类装饰定义
/// <summary>
    /// 具有保温接口的材料,提供保温功能,相当于ConcreteDecoratorB类型
    /// </summary>
    public sealed class KeepWarmDecorator : DecorationStrategy
    {
        public KeepWarmDecorator(House house) : base(house) { }

        public override void Renovation()
        {
            base.Renovation();
            Console.WriteLine("增加保温的功能");
        }
    }
调用
public void RunTest()
        {
            //这就是我们需要装饰的房子
            House myselfHouse = new MyHouse();

            DecorationStrategy securityHouse = new HouseSecurityDecorator(myselfHouse);
            securityHouse.Renovation();

            /*
             * 此时房子就有了安全系统了.....
             */

            //【1】如果我既要安全系统又要保暖呢,继续装饰就行
            //DecorationStrategy securityAndWarmHouse = new KeepWarmDecorator(myselfHouse);
            //securityAndWarmHouse.Renovation();


            Console.WriteLine("\r\n*****************************\r\n");

            //【2】如果我既要安全系统又要保暖呢,继续装饰就行【和上边的进行运行比对】
            //【对运行结果难理解的话,打断点单步执行进行理解】

            DecorationStrategy securityAndWarmHouse1 = new KeepWarmDecorator(securityHouse);
            securityAndWarmHouse1.Renovation();
        }

image

装饰模式的优缺点

优点
  • 把抽象接口与其实现解耦。

  • 抽象和实现可以独立扩展,不会影响到对方。

  • 实现细节对客户透明,对用户隐藏了具体实现细节。

缺点
  • 增加了系统的复杂度
更多推荐

【C++】map与set的封装

文章目录前言正文1.类型的泛化2.仿函数3.迭代器3.1正向迭代器3.1.1++3.1.2--3.1.3*3.1.4->3.1.5!=完整版代码4.[](map)框架1.红黑树2.set3.map总结前言在学习了红黑树之后,我们便可以尝试初步的在红黑树的基础上封装出map与set,好了,话不多说,进入今天的学习吧!所需

AVL 树

文章目录一、AVL树的概念二、AVL树的实现1.AVL树的存储结构2.AVL树的插入一、AVL树的概念在二叉搜索树中,当我们连续插入有序的数据时,二叉搜索树可能会呈现单枝树的情况,此时二叉搜索树的查找效率为O(N)俄罗斯的两位数学家G.M.Adelson-Velsky和E.M.Landis发明了AVL树可以解决上述问题

【计算机毕业设计】基于SpringBoot+Vue贵州旅游系统的设计与实现

博主主页:一季春秋博主简介:专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发,远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容:毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题库、技术咨询。🍅文末获取联系🍅精彩专栏推荐订阅👇🏻👇🏻不然下次找不到哟Sp

0/17 SAP Master Data Governance(SAP 主数据治理)

SAPMasterDataGovernanceTheComprehensiveGuidetoSAPMDG(SAP主数据治理-SAPMDG综合指南)HowThisBookIsOrganized这本书是如何组织的Chapter1Thischapterstartswithanintroductionintothevariou

C++ 太卷,转 Java?

最近看到知乎、牛客等论坛上关于C++很多帖子,比如:2023年大量劝入C++2023年还建议走C++方向吗?看了一圈,基本上都是说C++这个领域唯一共同点就是都使用C++语言,其它几乎没有相关性。的确是这样,比如量化交易、自动驾驶,客户端,图形学,存储数据库开发,后台开发,嵌入式等等基本上都有各自的领域知识。那么为什么

循环经济下的新赛道妃鱼助力二手奢侈品行业变革

自2016年以来,随着国家对于闲置物品利用的政策文件连续发布,我们可以明确地看到一个趋势:我国正在积极鼓励和支持循环经济的发展,这不仅是政策层面的指导,更是反映了新一代消费者的消费观念的转变,在这样的大背景趋势下,二手奢侈品市场开始崭露头角,国泰君安研究报告显示,中国闲置高端消费品零售市场规模已从2016年162亿元增

【光伏系统】将电流从直流转换为交流电的太阳能逆变器、太阳能跟踪系统来提高系统的整体性能及集成电池解决方案(Simulink仿真)

💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。⛳️座右铭:行百里者,半于九十。📋📋📋本文目录如下:🎁🎁🎁目录💥1概述📚2运行结果🎉3参考文献🌈4Simulink仿真实现💥1概述本文介绍了太阳能仿真技术及其各个组成部分。太阳

NoSQL之 Redis配置与优化

目录1、关系数据库与非关系型数据库1.1关系型数据库1.2非关系型数据库1.3关系型数据库和非关系型数据库区别1.4非关系型数据库产生背景2、Redis2.1简介2.2Redis具有以下几个优点2.3Redis为什么这么快?3、Redis安装部署3.1Redis命令工具3.2redis-cli命令行工具3.3redis

金融领域:产业链知识图谱包括上市公司、行业和产品共3类实体,构建并形成了一个节点10w+,关系边16w的十万级别产业链图谱

项目设计集合(人工智能方向):助力新人快速实战掌握技能、自主完成项目设计升级,提升自身的硬实力(不仅限NLP、知识图谱、计算机视觉等领域):汇总有意义的项目设计集合,助力新人快速实战掌握技能,助力用户更好利用CSDN平台,自主完成项目设计升级,提升自身的硬实力。专栏订阅:项目大全提升自身的硬实力[专栏详细介绍:项目设计

SpaceX预计到2022年Starlink用户将达到2000万,但最终达到了100万

SpaceX的Starlink部门还没有接近实现客户和收入的预测,该公司在建立卫星网络之前与投资者分享了这一点华尔街日报报道今天出版。据报道,2015年的一份题为“SpaceX用来从投资者那里筹集资金”的报告预计,到2022年,Starlink的订户将达到2000万人,并产生近120亿美元的收入和70亿美元的营业利润。

【LLM】金融大模型场景和大模型Lora微调实战

文章目录一、金融大模型背景二、大模型的研究问题三、大模型技术路线四、LLaMA家族模型五、Lora模型微调的原理六、基于mt0-large进行Lora微调实战七、对chatglm2进行lora微调Reference一、金融大模型背景金融行业需要垂直领域LLM,因为存在金融安全和数据大多数存储在本地,在风控、精度、实时性

热文推荐