引言

当我们完成一个软件产品开发后就需要对其进行各种测试,适配快速迭代下质量的保障。当有一个完善的产品的对象后,如果我们想要给他添加一个测试功能,那么我们可以用一个新的类去装饰它来实现对原有对象职责的扩展。新的类称为“装饰者”,原有的对象称为“被装饰者”。这种模式被称为装饰器模式。

概念

装饰器模式(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)的更多相关文章

  1. 浅谈设计模式--装饰者模式(Decorator Pattern)

    挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...

  2. 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

    装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...

  3. 设计模式 - 装饰者模式(Decorator Pattern) 具体解释

    装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...

  4. 23种设计模式之装饰器模式(Decorator Pattern)

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

  5. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  6. c#设计模式之装饰器模式(Decorator Pattern)

    引子 在面向对象语言中,我们常常会听到这样一句话:组合优于继承.那么该如何去理解这句话呢? 下面我将以游戏装备为模型用简单的代码去展示它 先创建一个装备的抽象类,然后创建刀枪2个具体的业务子类 pub ...

  7. 设计模式(三)——装饰器模式(Decorator Pattern)

    发现太过于刻意按照计划来写博客,有点不实际,刚好最近在一个网课上复习AOP的知识,讲到了装饰器模式和代理模式,顺便复习总结一下. 首先了解一下装饰器模式,从名字里面可以看出来,装饰器模式就类似于房子装 ...

  8. 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现

    返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...

  9. 说说设计模式~装饰器模式(Decorator)

    返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...

  10. 用最简单的例子理解装饰器模式(Decorator Pattern)

    假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格.最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格. 每个产品都有名称和价格,首先设计一个关于产品的 ...

随机推荐

  1. Kubernetes 搭建 ES 集群(存储使用 local pv)

    一.集群规划 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化. ES 集群的 master 节点至少需要三个,防止脑裂. 由于 master 在配置过程中需要保证主机名固 ...

  2. 一起学Vue:UI框架(element-ui)

    目标 使用Vue+ElementUI构建一个非常简单CRUD应用程序,以便您更好地了解它的工作方式. 效果页面 比如我们要实现这样列表.新增.编辑三个页面: 列表页面 新增页面 编辑页面 安装elem ...

  3. python使用zlib库压缩图片,使用ffmpeg压缩视频

    python压缩图片.视频 图片压缩使用zlib库 视频压缩使用工具ffmpeg # ffmpeg -i 1.mp4 -r 10 -pix_fmt yuv420p -vcodec libx264 -p ...

  4. 热部署只知道devtools吗?JRebel不香吗?

    持续原创输出,点击上方蓝字关注我 目录 前言 JRebel收费怎么破? 什么是本地热部署? 什么是远程热部署? JRebel和devtools的区别 如何安装JRebel? 如何本地热部署? 如何远程 ...

  5. 《Clojure编程》笔记 第3章 集合类与数据结构

    目录 背景简述 第3章 集合类与数据结构 3.1 抽象优于实现 3.1.1 Collection 3.1.2 Sequence 3.1.3 Associative 3.1.4 Indexed 3.1. ...

  6. 剑指offer之打印超过数组一半的数字

    问题描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  7. CO函数库

    CO函数库 用于 Generator 函数的自动执行,co函数返回一个promise对象 Generator 函数: 协程的概念:A执行- A暂停,执行权给B--- B交回执行权--- A恢复执行 G ...

  8. 谈谈对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)

    一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...

  9. SU模型叠加实景三维模型 用它就可以实现了

    草图大师SketchUp是一套直接面向设计方案创作过程的设计软件,使用SketchUp规划设计师可以从潦草的平面草图开始,创建出想像的任何东西 .虽然市面软件众多,也不能取代SketchUp独有的位置 ...

  10. php 获取抖音id

    <?php public function getid($dy_url){ $header=get_headers($dy_url); $str = "/^.*?(\d+).*/&qu ...