一、定义

装饰者模式,英文叫Decorator Pattern,在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。

设计原则:

1. 多用组合,少用继承。

利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

2. 类应设计的对扩展开放,对修改关闭。

要点:

1. 装饰者和被装饰对象有相同的超类型。

2. 可以用一个或多个装饰者包装一个对象。

3. 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。

4. 对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象。

5. 装饰模式中使用继承的关键是想达到装饰者和被装饰对象的类型匹配,而不是获得其行为。

6. 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。在实际项目中可以根据需要为装饰者添加新的行为,做到“半透明”装饰者。

7. 适配器模式的用意是改变对象的接口而不一定改变对象的性能,而装饰模式的用意是保持接口并增加对象的职责

二、结构

装饰者模式的实现类图:

从图中可以看出装饰着模式包含如下参与者:

1、一个被包装类和包装类均需遵守的接口——IComponent;

2、被包装类——ConcreteComponent;

3、包装类的抽象类——Decorator;

4、包装类的具体实现——DecoratorA、DecoratorB;

5、发起调用的客户端程序——Client。

三、实现

产品类

///

///商品类///

public classProduct

{public int Id { get; set; }public string Name { get; set; }

}

产品块

///

///产品块接口-被包装对象和包装对象均实现此接口///

public interfaceIProductsBlock

{

ListGetProductsBlock();

}///

///基本商品块-被包装的基础对象///

public classProductsBlock : IProductsBlock

{public ListGetProductsBlock()

{

List products = new List() {new Product() { Id = 11, Name = "一般商品1"},new Product() { Id = 12, Name = "一般商品2"},new Product() { Id = 13, Name = "一般商品3"}

};returnproducts;

}

}///

///包装类的抽象父类///

public abstract classBlockDecorator : IProductsBlock

{protectedIProductsBlock block;publicBlockDecorator(IProductsBlock block)

{this.block =block;

}public abstract ListGetProductsBlock();

}///

///附加广告商品的包装器实现///

public classAdDecorator : BlockDecorator

{publicAdDecorator(IProductsBlock block)

:base(block)

{ }public override ListGetProductsBlock()

{

List adProducts = new List(){new Product() { Id = 11, Name = "广告商品1"},new Product() { Id = 12, Name = "广告商品2"}

};var list = this.block.GetProductsBlock();

list.InsertRange(0, adProducts);returnlist;

}

}///

///附加降价商品的包装类实现///

public classCutPriceDecorator : BlockDecorator

{publicCutPriceDecorator(IProductsBlock block)

:base(block)

{ }public override ListGetProductsBlock()

{

List adProducts = new List() {new Product() { Id = 21, Name = "降价商品1"},new Product() { Id = 22, Name = "降价商品2"}

};var list = this.block.GetProductsBlock();

list.InsertRange(0, adProducts);returnlist;

}

}

调用

//组装过程

IProductsBlock block = newProductsBlock();

block= new CutPriceDecorator(block);//后期新增的降价商品

block= newAdDecorator(block);//对客户程序来说,包装是透明的

var products =block.GetProductsBlock();foreach (var p inproducts)

{

Console.WriteLine(p.Name);

}

Console.WriteLine("按任意键结束...");

Console.ReadKey();

四、适用场景

1、 想透明并且动态地给对象增加新的职责的时候。

2、 给对象增加的职责,在未来存在增加或减少可能。

3、 用继承扩展功能不太现实的情况下,应该考虑用组合的方式。

五、优缺点

装饰者模式的优点:

1、 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。

2、 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。

3、 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。

4、 装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。

5、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

装饰者模式的缺点:

1、 装饰链不能过长,否则会影响效率。

2、 因为所有对象都是Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),也就是说,通过继承建立的关系总是脆弱地,如果基类改变,势必影响对象的内部,而通过组合(Decoator HAS A Component)建立的关系只会影响被装饰对象的外部特征。

3、只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。

六、.NET中装饰者模式的实现

在.NET 类库中也有装饰者模式的实现,该类就是System.IO.Stream,下面看看Stream类结构:

上图中,BufferedStream、CryptoStream和GZipStream其实就是两个具体装饰类,这里的装饰者模式省略了抽象装饰角色(Decorator)。下面演示下客户端如何动态地为MemoryStream动态增加功能的。

MemoryStream memoryStream = new MemoryStream(new byte[] {95,96,97,98,99});

//扩展缓冲的功能

BufferedStream buffStream = newBufferedStream(memoryStream);

//添加加密的功能

CryptoStream cryptoStream = new CryptoStream(memoryStream,newAesManaged().CreateEncryptor(),CryptoStreamMode.Write);

//添加压缩功能

GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, true);

装饰者模式采用对象组合而非继承的方式实现了再运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的 ”灵活性差“和”多子类衍生问题“。

同时它很好地符合面向对象设计原则中 ”优先使用对象组合而非继承“和”开放-封闭“原则。

主要参考文章:http://www.cnblogs.com/zdy_bit/archive/2012/08/31/2665716.html

米线店结账程序 装饰着模式_Head First设计模式之装饰者模式相关推荐

  1. 米线店结账程序 装饰着模式_实验报告2_装饰者模式

    序号: 姓名: 杨林燕 学号: 106 专业: 软件工程 日期: 成绩: 实验二 装饰者模式的运用 一.实验目的: 装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹 性的替代 ...

  2. 米线店结账程序 装饰着模式_装饰者模式的运用

    实 验 报 告 实验二 装饰者模式的运用 一.实验目的: 装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹 性的替代方案.在熟悉装饰者模式相关理论知识的基础上,使用装设者模式 ...

  3. 米线店结账程序 装饰着模式_米线店整体装修设计方案图 4款云南过桥米线加盟店47平米室内设计图...

    米线店整体装修设计方案图 4款云南过桥米线加盟店47平米室内设计图 云南过桥米线加盟店内部的布置设计散发着中式的气息,宽敞的内部空间很有特色,顶棚石膏天花板无吊顶铺设很规整,再加上方形的长条灯池搭配, ...

  4. 米线店结账程序 装饰着模式_设计模式——装饰者模式

    <Head First 设计模式> 学习笔记,码云同步更新中 如有错误或不足之处,请一定指出,谢谢~ 目录 查看其它设计模式笔记,点这里→设计模式笔记汇总 装饰者模式 定义: 动态地将责任 ...

  5. 米线店结账程序 装饰着模式_海底捞推出三个子品牌 主打餐饮10元店模式

    中国商报/中国商网(记者 贺阳)近日,海底捞旗下的自有子品牌密集入市.中国商报记者梳理发现,主打土豆粉的"乔乔的粉"将于近期开业,售卖米线.水饺的"孟小将"&q ...

  6. 米线店结账程序 装饰着模式_真实数据:外卖销售9999+ 长沙米线万单店 它究竟是怎么做到的?...

    对于餐饮来说,最期望达成的是什么,那一定是月售:9999+的万单店了.万单店如高山仰止,只能心向往之,想做到真的太难了.特别是在疫情期间,餐饮重创,许多品牌生存都艰难,更别提冲击万单店了,孟婆家的酸汤 ...

  7. 米线店结账程序 装饰着模式_设计模式(三)装饰者模式

    装饰者模式是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案.装饰者模式动态地将责任附加到对象身上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案,比生成子类更加灵活. 通常在继承关系 ...

  8. 装饰者模式 php,PHP设计模式之装饰器模式

    装饰器设计模式 什么是装饰器模式 装饰器模式就是对一个已有的结构增加装饰.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象 ...

  9. java设计模式装饰者模式优点_java设计模式之--装饰者模式

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

最新文章

  1. Socket的3次握手链接与4次断开握手
  2. springboot学习笔记-01-springboot-helloworld的编写以及原理初步了解(自动装配)
  3. 那个悲伤的朋友,去了一趟菜场竟然活过来了
  4. Mysql学习总结(44)——Linux下如何实现mysql数据库每天自动备份定时备份
  5. linux寻找依赖文件
  6. OPENROWSET访问CSV格式文件
  7. js如何监听元素事件是否被移除_javascript:什么是js事件?(上)
  8. 27_iOS干货19之网络4_在线http/https素材资源
  9. Docker Desktop安装
  10. linux locale 编译,Linux locale 缺失和安装
  11. MFC——EDIT空间显示内容大小限制在32K,如何解除?
  12. Google Professional Data Engineer(PDE)考试
  13. 小程序源码:独家修复登录接口社区论坛-多玩法安装简单
  14. 基于SABR模型的期权波动率曲线套利策略
  15. Java练习之复数运算
  16. 带属性随机游走的图循环网络
  17. 关于编码器8k超清,海图科技编码器的评估
  18. 安卓开发选取城市列表
  19. Astah Sequence Diagram图
  20. [华中科技计组实验]logisim完成单周期5级流水MIPS CPU

热门文章

  1. 空间金字塔匹配 matlab,基于核函数匹配的空间金字塔物体识别方法
  2. 苹果xsmax有高通基带吗_高通基带终于来了!彻底抛弃英特尔的苹果12:信号真的稳了吗?...
  3. 3D木门家居建材行业的时尚弄潮儿
  4. 利用微软小冰 API 接口,对大量照片进行颜值评分
  5. 战地之王枪械:近战之王870
  6. 如何学习NgZorro的源码
  7. UML对基于B/S模式的图书管理系统的分析与设计
  8. python综合实训项目教程_Python安全编程项目实训教程
  9. 在360浏览器怎么找html,360浏览器,小编教你怎么找360浏览器收藏夹路径
  10. Android中如何加载大图片和长图片