C#设计模式-装饰器模式(Decorator Pattern)
引言
当我们完成一个软件产品开发后就需要对其进行各种测试,适配快速迭代下质量的保障。当有一个完善的产品的对象后,如果我们想要给他添加一个测试功能,那么我们可以用一个新的类去装饰它来实现对原有对象职责的扩展。新的类称为“装饰者”,原有的对象称为“被装饰者”。这种模式被称为装饰器模式。
概念
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
结构图

装饰器模式中的角色:
- 抽象构件(Component)角色:声明封装器和被封装对象的公用接口。即给出一个抽象接口,已规范准备接收附加责任的对象。
- 具体构件(ConcreteComponent)角色:类是被封装对象所属的类。 它定义了基础行为, 但装饰类可以改变这些行为。
- 装饰(Decorator)角色:拥有一个指向被封装对象的引用成员变量。 该变量的类型应当被声明为通用部件接口, 这样它就可以引用具体的部件和装饰。 装饰基类会将所有操作委派给被封装的对象。
- 具体装饰(ConcreteDecorator)角色:定义了可动态添加到部件的额外行为。 具体装饰类会重写装饰基类的方法, 并在调用父类方法之前或之后进行额外的行为。负责给构件对象“贴上”附加的责任。
实现
实现一个开发完成后的产品,对其进行手工功能测试、自动化测试、压力测试。将产品作为被装饰者,也就是构件。各种测试作为装饰者,计算附加不同的测试花费的总时间。
实现思路:
- 定义一个产品抽象类。
- 实现具体的产品,具体的产品继承产品抽象类。
- 定义一个测试类型的抽象装饰类,继承产品抽象类。
- 实现不同类型的测试,继承测试类型的抽象装饰类。
- 使用时实例化一个产品,然后对产品进行附件不同的测试类型。
using System; namespace Decorator
{
class Program
{
static void Main(string[] args)
{
Product a = new ProductA();
Console.WriteLine($"未执行{a.Test}测试时总共花费时间{a.TotalTime}");
a = new ManualTest(a);
Console.WriteLine($"执行{a.Test}总共花费时间{a.TotalTime}");
Console.WriteLine("====================================="); Product b = new ProductB();
b = new ManualTest(b);
b = new StressTest(b);
b = new AutoTest(b);
Console.WriteLine($"执行{b.Test}总共花费时间{b.TotalTime}"); Console.Read();
}
} /// <summary>
/// 一个项目产品,抽象构件
/// </summary>
public abstract class Product
{
public string Name { get; set; }
public double SpendTime { get; set; }
public abstract string Test { get; }
public abstract double TotalTime { get; }
} /// <summary>
/// 具体的项目产品A,具体构件
/// </summary>
public class ProductA : Product
{
public ProductA()
{
Name = "ProductA";
SpendTime = 0;
} public override string Test => this.Name;
public override double TotalTime => this.SpendTime;
} /// <summary>
/// 具体的项目产品B,具体构件
/// </summary>
public class ProductB : Product
{
public ProductB()
{
Name = "ProductB";
SpendTime = 0;
} public override string Test => this.Name;
public override double TotalTime => this.SpendTime;
} /// <summary>
/// 测试类型,抽象装饰
/// </summary>
public abstract class TestType : Product
{
Product _product = null; public TestType(Product product)
{
_product = product;
} public override string Test
{
get
{
return _product.Test + "+" + this.Name;
}
} public override double TotalTime
{
get
{
return _product.TotalTime + this.SpendTime;
}
}
} /// <summary>
/// 手工测试类型,具体装饰
/// </summary>
public class ManualTest : TestType
{ public ManualTest(Product product) : base(product)
{
Name = "手工测试";
SpendTime = 200;
}
} /// <summary>
/// 自动化测试类型,具体装饰
/// </summary>
public class AutoTest : TestType
{ public AutoTest(Product product) : base(product)
{
Name = "自动化测试";
SpendTime = 100;
} } /// <summary>
/// 压力测试类型,具体装饰
/// </summary>
public class StressTest : TestType
{
public StressTest(Product product) : base(product)
{
Name = "压力测试";
SpendTime = 200;
}
} }
运行后结果:
未执行ProductA测试时总共花费时间0
执行ProductA+手工测试总共花费时间200
=====================================
执行ProductB+手工测试+压力测试+自动化测试总共花费时间500
应用场景
- 在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为时可以使用装饰模式。因为装饰能将业务逻辑组织为层次结构,可为各层创建一个装饰, 在运行时将各种不同逻辑组合成对象。 由于这些对象都遵循通用接口, 客户端代码能以相同的方式使用这些对象。
- 如果用继承来扩展对象行为的方案难以实现或者根本不可行,可以使用装饰模式。
优缺点
优点
- 无需创建新子类即可扩展对象的行为。
- 可以在运行时添加或删除对象的功能。
- 可以用多个装饰封装对象来组合几种行为。
- 装饰类和被装饰类可以独立发展,不会相互耦合。
- 单一职责原则。 可以将实现了许多不同行为的一个大类拆分为多个较小的类。
缺点
- 在封装器栈中删除特定封装器比较困难。
- 实现行为不受装饰栈顺序影响的装饰比较困难。
- 各层的初始化配置代码看上去可能会很糟糕。
C#设计模式-装饰器模式(Decorator Pattern)的更多相关文章
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
- 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法
装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...
- 设计模式 - 装饰者模式(Decorator Pattern) 具体解释
装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...
- 23种设计模式之装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包 ...
- python 设计模式之装饰器模式 Decorator Pattern
#写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...
- c#设计模式之装饰器模式(Decorator Pattern)
引子 在面向对象语言中,我们常常会听到这样一句话:组合优于继承.那么该如何去理解这句话呢? 下面我将以游戏装备为模型用简单的代码去展示它 先创建一个装备的抽象类,然后创建刀枪2个具体的业务子类 pub ...
- 设计模式(三)——装饰器模式(Decorator Pattern)
发现太过于刻意按照计划来写博客,有点不实际,刚好最近在一个网课上复习AOP的知识,讲到了装饰器模式和代理模式,顺便复习总结一下. 首先了解一下装饰器模式,从名字里面可以看出来,装饰器模式就类似于房子装 ...
- 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现
返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...
- 说说设计模式~装饰器模式(Decorator)
返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...
- 用最简单的例子理解装饰器模式(Decorator Pattern)
假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格.最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格. 每个产品都有名称和价格,首先设计一个关于产品的 ...
随机推荐
- window 属性:自定义元素(custom elements)
概述 Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签),而往常,开发者不得不写一大堆冗长.深层嵌套的标 ...
- HBase基础理论知识
来源:第四章:大数据 の HBase 基础 本课主题 NoSQL 数据库介绍 HBase 基本操作 HBase 集群架构与设计介紹 HBase 与HDFS的关系 HBase 数据拆分和紧缩 引言 ...
- SpringBoot整合JPA遇到的问题
在学习SpringBoot中使用Repository时出现这种错误 或者使用findOne也会报错,只需要改为 应该是SpringBoot版本的原因,fingOne()方法好像已经不用了.
- python的多线程和java的多线程之间的区别
在python中,由于Cpython解释器的全局解释器的存在,那么多线程的话在同一时刻只能有一个线程执行,意思就是python中的多线程只能并发执行, 没有办法实现真正的并行,也就是无法利用多核CPU ...
- DevOps 视角的前后端分离与实战
本文作者:CODING - 廖红坤 前言 随着微前端.微服务等技术理念和架构的蓬勃发展,我们已经没必要去讨论为什么要前后端分离这种话题,前后端分离已成为互联网项目开发的标准模式.前后端在各自的领域发展 ...
- Linux 系统编程 学习:00-有关概念
Linux 系统编程 学习:00-有关概念 背景 系统编程其实就是利用系统中被支持的调度API进行开发的一个过程. 从这一讲开始,我们来介绍有关Linux 系统编程的学习. 知识 在进行Linux系统 ...
- pycharm pro2020版专业版永久激活
pycharm2020版本专业版永久激活[亲测有效] pycharm2020.1版安装包与破解工具下载 可私信我获取资源. 公众号,轻松学编程 教程 1.先下载安装包和破解补丁压缩包,然后点击pych ...
- Flask简介与启动服务器
Flask 一.简介 官方文档:http://flask.pocoo.org/ http://www.pythondoc.com/flask/index.html(中文) 1.概述 flask是一个非 ...
- git rebase的时候捅娄子了,怎么办?在线等……
大家在使用git的过程当中有闯过祸吗? 我闯过,我闯的第一个祸就是使用git rebase造成的,虽然后来最终还是解决了,但是还是给我吓得不轻.当时的事情是这样的. 我们来看下这张图: 简单解释一下这 ...
- CF1066F Yet another 2D Walking
DP 由图可以知道优先级相同的点都在一个"7"字形中 所以在走当前的优先级的点时最好从右下的点走到左上的点,或从从左上的点走到右下的点 那记dp[i][0]表示在走完第i个优先级时 ...