装饰者模式(Decorator Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/405 访问。

装饰者模式属于结构型模式,装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。

装饰者模式通过创建一个包装对象(wrapper),也就是用装饰来包裹真实的对象。

角色:

1、抽象构件(Component)

给出一个抽象接口,以规范准备接收附加责任的对象;

2、具体构件(Concrete Component)

定义一个将要接收附加责任的类;

3、抽象装饰(Decorator)

持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口;

4、具体装饰(Concrete Decorator)

负责给构件对象添加上附加的责任。

示例:

命名空间DecoratorPattern中包含汽车Car类、玛莎拉蒂Maserati类、法拉利Fabbrica类、酷汽车CoolCar类、汽车车贴Paster类和汽车遮阳挡Visor类。本示例通过使用装饰者模式为汽车进行一次简单的外观装饰。

namespace DecoratorPattern
public abstract class Car {

    public string Name { get; set; }

    public abstract void StartUp();

}

汽车基类Car,充当抽象构件。

public class Fabbrica : Car {

    public Fabbrica() {
Name = "Fabbrica";
} public override void StartUp() {
Console.WriteLine($"{Name} is starting!");
} }

法拉利Fabbrica类,充当具体构件。

public class Maserati : Car {

    public Maserati() {
Name = "Maserati";
} public override void StartUp() {
Console.WriteLine($"{Name} is starting!");
} }

玛莎拉蒂Maserati类,充当具体构件。

public abstract class CoolCar : Car {

    protected Car _car = null;

    public CoolCar(Car car) {
_car = car;
} public override void StartUp() {
Console.WriteLine($"{_car.Name} is starting!");
} }

酷汽车CoolCar类,充当抽象装饰。

public class Paster : CoolCar {

    public Paster(Car car) : base(car) {

    }

    public override void StartUp() {
SetPaster();
base.StartUp();
} private void SetPaster() {
Console.WriteLine($"Set paster to {_car.Name}!");
} }

汽车车贴Paster类,通过继承CoolCar类,为对汽车进行装饰提供了可能。

public class Visor : CoolCar {

    public Visor(Car car) : base(car) {

    }

    public override void StartUp() {
SetVisor();
base.StartUp();
} private void SetVisor() {
Console.WriteLine($"Set visor to {_car.Name}!");
} }

汽车遮阳挡Visor 类,通过继承CoolCar类,为对汽车进行装饰提供了可能。

public class Program {

    private const string LINE_SPLIT = "-------------------------";

    private static Car _car = null;

    private static CoolCar _coolCar = null;

    public static void Main(string[] args) {
_car = new Maserati(); _coolCar = new Visor(_car);
_coolCar.StartUp();
Console.WriteLine(LINE_SPLIT); _car = new Fabbrica(); _coolCar = new Paster(_car);
_coolCar.StartUp();
Console.WriteLine(LINE_SPLIT); Console.ReadKey();
} }

以上是调用方的代码,以下是这个案例的输出结果:

Set visor to Maserati!
Maserati is starting!
-------------------------
Set paster to Fabbrica!
Fabbrica is starting!
-------------------------

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/405 访问。

1、装饰者模式与继承关系的目的都是要扩展对象的功能,但是装饰者模式可以提供比继承更多的灵活性;

2、通过使用不同的具体装饰类以及这些装饰类的排列组合,开发者可以创造出很多不同行为的组合。

缺点:

1、这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性;

2、装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂;

3、装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

使用场景:

1、需要扩展一个类的功能,或给一个类添加附加职责;

2、需要动态的给一个对象添加功能,这些功能可以再动态的撤销;

3、需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实;

4、当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸式增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

C#设计模式之9-装饰者模式的更多相关文章

  1. JAVA设计模式之【装饰者模式】

    JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...

  2. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  3. 【读书笔记】读《JavaScript设计模式》之装饰者模式

    一.定义 装饰者模式可用来透明地把对象包装在具有同样接口的另一个对象之中.这样一来,你可以给一个方法添加一些行为,然后将方法调用传递给原始对象.相对于创建子类来说,使用装饰者对象是一种更灵活的选择(装 ...

  4. 设计模式学习心得<装饰器模式 Decorator>

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...

  5. 设计模式のDecoratorPattern(装饰器模式)----结构模式

    一.产生背景 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...

  6. 设计模式C++实现——装饰者模式

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/walkerkalr/article/details/28633123 模式定义:         装 ...

  7. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  8. 《Head First 设计模式》之装饰者模式

    作者:Grey 原文地址:http://www.cnblogs.com/greyzeng/p/5922248.html 模式名称 装饰者模式(Decorator Pattern) 需求 定义咖啡厅中的 ...

  9. 设计模式学习之装饰者模式(Decorator,结构型模式)(16)

    参考地址:http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一.定义:装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相 ...

  10. [设计模式] javascript 之 装饰者模式

    装饰者模式说明 说明:通一个类来动态的对另一个类的功能对象进行前或后的修饰,给它辅加一些额外的功能; 这是对一个类对象功能的装饰,装饰的类跟被装饰的类,要求拥有相同的访问接口方法(功能),这在动态面向 ...

随机推荐

  1. vscode安装rainbow-fart(彩虹屁)插件,程序员只能自我鼓励了!!!

    2020-7-10更新 Rainbow Fart 插件现以发布到 VSCode 商店,安装过 VSIX 版本的用户请卸载之前的版本,从商店安装. 从 VSCode 扩展商店 下载并安装.(更新vsco ...

  2. Ethical Hacking - Web Penetration Testing(4)

    CODE EXECUTION VULNS Allows an attacker to execute OS commands. Windows or Linux commands. Can be us ...

  3. vue : history模式与项目部署的爬坑

    需求:url不能有#符号,且不放在服务器虚拟主机的根目录. 假设放在虚拟主机的 medicine 文件夹下. 需要改两个文件,一个是 ./config/index.js (vue设置文件) ,另一个是 ...

  4. Linux好学吗?怎么自学Linux?6个值得你去学习Linux的理由!

    两个多月前,我对日常工作做出了一个非常重要的决定-我决定从Windows切换到Linux,将其作为个人和办公笔记本电脑的主要系统.除了开始时一些小的驱动程序问题之外,切换非常平稳,我不会考虑返回.如果 ...

  5. Shell基本语法---shell数组

    shell数组 arr=( ) #定义数组 echo ${#arr[*]} #打印数组长度 echo ${arr[]} #打印数组的第一个成员 echo ${arr[]} #打印数组的二个成员 ech ...

  6. XML转Bean

    XML转Bean有很多方式,我使用的是xtream方式实现xml与bean的互转. 下面是简单的xml转bean /** * XML转换成bean * @param obj * @return yuy ...

  7. 循序渐进nginx(三):日志管理、http限流、https配置,http_rewrite模块,第三方模块安装,结语

    目录 日志管理 access_log error_log 日志文件切割 自定义错误页 http访问限流 限制请求数 语法 使用 限制连接数 语法 测试 补充: https配置 使用 生成证书 配置ng ...

  8. 面试题十七:打印从1到最大的n位数

    输入数字n,按顺序打印到最大的n位数 注意:没有规定类型,无论int或long 都会有可能溢出. 应当选择其他类型如String 方法一:定义长度与位数相同的字符数组,从0开始进行加一操作打印 pub ...

  9. ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3. ...

  10. emacs org-mode 中文手册精简版(纯小白)

    一只小白看了大佬的讲解视频结合其他大佬给整理的笔记再结合emacs 官方英文手册,觉得自己的知识好像增加了. 当时自己在全网搜索的时候没有看到那种纯小白的手册,本小白就写了这个,就当奉献社会了.若有不 ...