C# 结构型设计模式----装饰器模式

1、简介

简要说明就是动态地给一个对象添加一些额外的职责。适用于需要扩展一个类的功能,或给一个类添加多个变化的情况。

装饰器,顾名思义就是在原有基础上添加一些功能。

装饰器模式中各个角色有:

        抽象构件(Component)角色:定义一个对象接口,可以给这些对象动态地添加一些职责。
        具体构件(ConcreteComponent)角色:定义了一个具体的对象,也可以给这个对象添加一些职责。
        抽象装饰类(Decorator)角色:持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口。
        具体装饰类(ConcreteDecorator)角色:负责给构件对象“贴上”一些附加的职责。

2、适用场景

扩展一个类的功能:原有类无法修改或者修改困难的情况下,对类进行多次扩展或功能性比较相互独立,有效防止多次扩展的情况下子类的膨胀。

动态增加或撤销功能:需要动态地给对象添加或移除功能时。

多个功能组合:需要实现多个功能的不同组合时。

 3、举例说明

现在有一个手机,其仅有打电话的功能。现在需要给它加一个看视频和放音乐的功能。

传统做法如下:

手机类:

/// <summary>
/// 手机类
/// </summary>
public class Phone
{
    public void Call()
    {
        Console.WriteLine("打电话");
    }
}

增加功能:

public class FYY:Phone
{
    public void Install()
    {
        Console.WriteLine("放音乐!");
    }
}

public class FSP : Phone
{
    public void Install()
    {
        Console.WriteLine("放视频!");
    }
}

使用:

private void WTBtn_Click(object sender, EventArgs e)
{
    Phone phone0 = new Phone();//旧版手机
    phone0.Call();//仅有打电话的功能
    Console.WriteLine("\n");
    FYY phone = new FYY();//新版手机1
    phone.Call();//打电话,手机本来的功能
    phone.Install();//放音乐,给手机拓展的东西
    Console.WriteLine("\n");
    FSP phone1=new FSP();//新版手机2
    phone1.Call();//打电话,手机本来的功能
    phone1.Install();//放视频,给手机拓展的东西
}

可以看出,每当需要增加一个功能,就需要增加一个子类。这种简单的单一功能问题还不大,当你既要放音乐又要放视频的功能的话,那你要不就是再实现一个之类去包含两种功能,要不就多重继承让放音乐的类继承放视频的类。这样实例化放音乐的类就能达到使用两种功能。当需要的功能越多,继承就越深,或者有重复方法的类就越多。但这显然不科学。 装饰器模式就能很好解决此类问题。

装饰器模式

 抽象构件(Component)角色

 /// <summary>
 /// 抽象构件角色(Component)
 /// </summary>
 public abstract class IPhone
 {
     public abstract void Call();
 }

具体构件(ConcreteComponent)角色

 /// <summary>
 /// 具体构件角色(Concrete Component)
 /// </summary>
 public class Phone : IPhone
 {
     public override void Call()
     {
         Console.WriteLine("打电话");
     }
 }

抽象装饰类(Decorator)角色

/// <summary>
/// 抽象装饰类(Decorator)角色
/// </summary>
public abstract class PhoneDecorator : IPhone
{
    protected IPhone Phone { get; }

    public PhoneDecorator(IPhone phone)
    {
        Phone = phone;
    }

    /// <summary>
    /// 可以定义新增的功能方法,也可以不定义,直接给Call方法添加装饰
    /// </summary>
    public abstract void Install();
}

具体装饰类(ConcreteDecorator)角色

 /// <summary>
 /// 具体装饰类(ConcreteDecorator)角色
 /// </summary>
 // 放音乐功能装饰器
 public class YYDecorator : PhoneDecorator
 {
     public YYDecorator(IPhone phone) : base(phone)
     {
     }

     public override void Call()
     {
         base.Phone.Call();
         RunYY();//也可以给打电话这件事添加放音乐的功能
     }

     public override void Install()
     {
         Console.WriteLine("安装音乐!");
     }

     public void RunYY()
     {
         Console.WriteLine("语音通话!");
     }
 }


 /// <summary>
 /// 具体装饰类(ConcreteDecorator)角色
 /// </summary>
 // 放音乐功能装饰器
 public class SPDecorator : PhoneDecorator
 {
     public SPDecorator(IPhone phone) : base(phone)
     {
     }

     public override void Call()
     {
         base.Phone.Call();
         RunSP();//也可以给打电话这件事添加视频通话的功能
     }

     public override void Install()
     {
         Console.WriteLine("安装视频!");
     }
     public void RunSP()
     {
         Console.WriteLine("视频通话!");
     }
 }

使用:

 private void WTBtn_Click(object sender, EventArgs e)
 {
      IPhone phone = new Phone();//初始手机
 phone.Call();//初始手机打电话
 Console.WriteLine("");

 PhoneDecorator phone1 = new YYDecorator(phone);//语音通话手机
 phone1.Install();//安装语音通话功能
 phone1.Call();//安装语音通话功能的手机打电话
 Console.WriteLine("");

 PhoneDecorator phone2 = new SPDecorator(phone);//视频通话手机
 phone2.Install();//安装视频通话功能
 phone2.Call();//安装视频通话功能的手机打电话
 Console.WriteLine("");

 PhoneDecorator phone3 = new SPDecorator(phone);//视频的手机
 phone3.Install();//安装视频功能
 phone3 = new YYDecorator(phone3);//语音的手机
 phone3.Install();//安装音乐功能
 phone3.Call();//双支持的手机再打电话
 }

注意:Call()方法和Install()方法都是实现了装饰器,一个是给原本的功能前后添加功能段,一个是独立添加其他的功能。

可以看出使用装饰类如果需要实现组合配置,仅需要对像重新实例化即可,无需创建新的对象,和使用多重继承了。 若需要增加其他功能仅需要增加具体装饰类(ConcreteDecorator)角色即可。

最后:

优点:
1、灵活性:装饰器模式可以以动态的方式在运行时给对象增加额外的职责,而不需要在编译时决定添加哪些功能。通过使用装饰器模式,可以在不改变原始对象结构的情况下,根据需要灵活地扩展对象的行为。
2、可插拔:通过使用装饰器模式,可以将功能分解成一系列的装饰器类,使得代码更加模块化和易于维护。可以在运行时动态地组合和替换装饰器对象,从而改变对象的行为。
3、可扩展性:装饰器模式可以避免继承带来的类膨胀问题,因为你可以通过组合装饰器对象来扩展对象的行为,而不是通过继承来添加新的功能。
4、符合开闭原则:装饰器模式完全遵守开闭原则,即对扩展开放,对修改封闭。通过使用装饰器模式,可以方便地添加新的装饰器类来扩展对象的行为,而不需要修改原始对象的代码。

缺点:
1、代码量增加:装饰器模式需要创建很多小类,即使只添加一个功能,也要额外创建一个类,这会使得程序更复杂。
2、增加代码复杂度:使用装饰器模式不但需要实例化组件,还要把组件包装到装饰者中,这会增加代码的复杂度。
3、设计难度高:装饰器模式需要对系统进行全面理解,设计出结构良好的装饰器类和被装饰类,才能够达到预期的效果。
4、性能问题:由于装饰器模式需要在运行时动态地创建对象和调用方法,这可能会导致性能上的问题。

注意:过度使用装饰器模式可能会导致程序变得复杂,增加系统中类的数量,并可能产生大量小粒度对象,使得代码变得难以维护。因此,在使用装饰器模式时需要谨慎考虑设计是否合适。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

.NET内网实战:通过白名单文件反序列化漏洞绕过UAC

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧&#xff0c;对内网和后渗透感兴趣的朋友们可以订阅该电子报刊&#xff0c;解锁更多的报刊内容。 02基本介绍 03原理分析 在渗透测试和红…

基于echarts、php、Mysql开发的数据可视化大屏

大屏效果展示 管理员进入数据可视化页面将看到数据可视化大屏。大屏内容包括两个条形图&#xff0c;用于统计当前网站所有用户的MBTI 16型人格分布&#xff1b;玫瑰图&#xff0c;用于展示当前网站用户MBTI四个维度&#xff0c;八个字母的占比&#xff1b;折线图&#xff0c;用…

jenkins ssh 免密报错Host key verification failed.

jenkins 发布项目&#xff0c;ssh连接远程服务器时报错&#xff1a;Host key verification failed. 解决&#xff1a; 原因是生成的sshkey不是用的jenkins用户&#xff0c;所以切换用户到&#xff1a;jenkins重新生成sshkey su jenkins ssh-keygen -t rsa ssh-copy-id -i ~/…

一款专业获取 iOS 设备的 UDID 工具|一键获取iPhone iPad设备的 UDID

什么是UDID&#xff1f; UDID&#xff0c;是iOS设备的一个唯一识别码&#xff0c;每台iOS设备都有一个独一无二的编码&#xff0c;这个编码&#xff0c;我们称之为识别码&#xff0c;也叫做UDID&#xff08; Unique Device Identifier&#xff09; 扫描后系统提示输入密码&am…

封装ES高亮Yxh-Es

拉取代码 git拉取 yxh-elasticsearch: es基本封装工具 使用场景 我们拿游览器举例&#xff0c;我将我要搜索的内容输入到输入框进行搜索&#xff0c;游览器就会根据对应的内容查出文章中出现过的关键字&#xff0c;并加上样式&#xff0c;让我们看的更清晰。 我们以就是使用全文…

布谷语音源码服务器搭建环境及配置流程

布谷语音源码部署环境安装要求&#xff08;只有在相同的环境下才更容易避免一些不必要的麻烦&#xff09;&#xff1a;●安装Center OS 7.9&#xff0c;我们自己的服务器使用的是7.9建议相同系统&#xff0c;非强制●安装宝塔环境&#xff08;强烈推荐使用&#xff09;●安装软…

百度SEO中的关键词密度与内容优化研究【百度SEO专家】

大家好&#xff0c;我是百度SEO专家&#xff08;林汉文&#xff09;&#xff0c;在百度SEO优化中&#xff0c;关键词密度和关键词内容的优化对提升页面排名至关重要。关键词的合理布局与内容的质量是确保网页在百度搜索结果中脱颖而出的关键因素。下面我们将从关键词密度和关键…

RDKit|分子数据的聚类分析

分子数据的聚类分析 聚类分析是一种无监督学习技术,用于根据分子特征将分子分组成若干簇。每个簇中的分子在特征空间中应当相似,而不同簇之间的分子差异则较大。在化学信息学和药物设计中,聚类分析常用于化合物库的分组、潜在药物靶点的发现以及分子多样性分析。 1 聚类分…

k8s环境下rabbitmq安装社区插件:rabbitmq_delayed_message_exchange

怎么在k8s环境下的rabbitmq安装社区版插件:rabbitmq_delayed_message_exchange 在你的rabbit-value.yaml中加入以下行&#xff0c;然后使用helm重新安装&#xff08;最好把pvc也删了重新安装&#xff08;如果你的密码变化了的话&#xff09; 减少出错概率&#xff09; ## par…

【python】OpenCV—findContours(4.4)

文章目录 1、功能描述2、代码实现3、完整代码4、结果展示5、涉及到的库函数6、参考 1、功能描述 找出物体轮廓&#xff0c;根据 PCA 计算特征值和特征向量&#xff0c;绘制特征值和特征向量&#xff0c;来初步展示物体的方向 2、代码实现 导入库函数&#xff0c;读入图片&am…

【论文阅读笔记】VLP: A Survey on Vision-language Pre-training

目录 前言2 特征提取&#xff08;Feature extraction&#xff09;2.1.1 图象特征提取OD-based Region feature / RoIFreeze the pre-trained object detectorsGrid features&#xff08;网格特征&#xff09;CNN-GFsEnd-to-End Training&#xff08;端到端训练&#xff09;ViT-…

Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译

文章目录 前言一、介绍二、相关工作三、方法A. 问题表述B. 框架概述C. 群体系统的初始化D. 去中心化激光雷达-惯性状态估计 四. 实验A. 室内飞行B. 退化环境飞行C. 去中心化部署 五. 结论和未来工作 前言 原文&#xff1a;原文 准确的自我状态和相对状态估计是完成群体任务的关…

Apache Hive分布式容错数据仓库系统

Apache Hive™是一个分布式的、容错的数据仓库系统&#xff0c;它支持大规模的分析&#xff0c;并使用SQL方便地读取、写入和管理驻留在分布式存储中的pb级数据。 Apache Hive Apache Hive是什么 Apache Hive是一个分布式的、容错的数据仓库系统&#xff0c;支持大规模的分析…

Vue CLI: 安装、项目创建及基本概念指南,vue生命周期

只有经历地狱般的磨砺&#xff0c;才能练就创造出天堂的力量&#xff1b;只有流过血的手指&#xff0c;才能弹奏出世间绝唱 文章目录 vue-cli介绍安装创建项目入口文件修改文件夹名称的步骤ES6模块化单文件组件 vue生命周期vue动画 vue-cli 介绍 vue-lic是一个开发vue项目的脚…

Geotrust SSL证书

在数字化浪潮席卷全球的今天&#xff0c;互联网已成为信息交流与商业活动不可或缺的平台。然而&#xff0c;随着网络应用的深入&#xff0c;数据泄露、身份盗用、网络诈骗等安全问题也日益凸显&#xff0c;严重威胁着用户的隐私与财产安全。在这样的背景下&#xff0c;数字证书…

css实现边框双色凹凸半圆

整体效果如下图&#xff1a; 结构代码&#xff1a; <div classline-outside-wrap><div classwrap><img src../img/avatar2x.png/><div classcontent-wrap></div></div></div> 内凹框实现&#xff1a; .content-wrap{width:100%;he…

HarmonyOS:自定义组件冻结功能

一、简介 自定义组件冻结功能专为优化复杂UI页面的性能而设计&#xff0c;尤其适用于包含多个页面栈、长列表或宫格布局的场景。在这些情况下&#xff0c;当状态变量绑定了多个UI组件&#xff0c;其变化可能触发大量UI组件的刷新&#xff0c;进而导致界面卡顿和响应延迟。为了提…

Kafka相关API开发

(一)引入依赖 用API直接去操作kafka(读写数据)在实际开发中用的并不多&#xff0c;学习它主要还是为了加深对Kafka功能的理解。kafka的读写操作&#xff0c;实际开发中&#xff0c;是通过各类更上层的组件去实现。而这些组件在读写kafka数据时&#xff0c;用的当然是kafka的jav…

警务辅助人员管理系统小程序ssm+论文源码调试讲解

2系统关键技术 2.1 微信小程序 微信小程序&#xff0c;简称小程序&#xff0c;英文名Mini Program&#xff0c;是一种全新的连接用户与服务的方式&#xff0c;可以快速访问、快速传播&#xff0c;并具有良好的使用体验。 小程序的主要开发语言是JavaScript&#xff0c;它与普…

微服务设计模式 - 断路器模式 (Circuit Breaker Pattern)

微服务设计模式 - 断路器模式 (Circuit Breaker Pattern) 定义 断路器模式&#xff08;Circuit Breaker Pattern&#xff09;是云计算和微服务架构中的一种保护性设计模式&#xff0c;其目的是避免系统中的调用链出现故障时&#xff0c;导致系统瘫痪。通过断路器模式&#xff…