引子

在面向对象语言中,我们常常会听到这样一句话:组合优于继承.那么该如何去理解这句话呢?

下面我将以游戏装备为模型用简单的代码去展示它

先创建一个装备的抽象类,然后创建刀枪2个具体的业务子类

  public abstract class AbstractEquipment
{
public int Id { get; set; } public string Name { get; set; } public abstract void Attack();
} public class Gun : AbstractEquipment
{
public override void Attack()
{
Console.WriteLine("用枪攻击");
}
} class Sword : AbstractEquipment
{
public override void Attack()
{
Console.WriteLine("用剑攻击");
}
}

面对这样的场景,我们常常会提出这样的疑问:如何面对业务扩展?例如,此时需要添加一个新的功能:在装备攻击后,会提醒善恶值增加

在不修改业务子类的前提下,我们通过继承和组合两种不同的方式来解决,如下:

   //继承
public class GunInherit:Gun
{
public override void Attack()
{
base.Attack();
Console.WriteLine("善恶值增加");
}
} //组合
public class EquipmentCombination
{
private AbstractEquipment _equipment = null;
public EquipmentCombination(AbstractEquipment equipment)
{
_equipment = equipment;
} public void Attack()
{
_equipment.Attack();
Console.WriteLine("善恶值增加");
}
}

观察上述代码可以得到以下结论

继承:虽然代码少,但是强侵入,强关联,只能为特定类服务

组合:虽然加了一个全新类,增加了代码量,但是非常灵活

在这么少量的代码下,已经能够看到继承的劣势,那么随着功能需求的增加,仅仅靠继承来扩展业务,那将会带来巨大的弊端.

装饰器模式

装饰器模式是通过上述组合加继承的方式,动态的为业务类添加功能的一种设计模式

在这种设计模式之下,只需要添加一个新的装饰器,即可为业务类添加一个新的功能

首先对装饰器进行一次抽象,相比于单单组合的方式,这样可以减少代码复杂程度

      public class BaseEquipmentDecorator : AbstractEquipment
{
private AbstractEquipment _equipment = null;
public BaseEquipmentDecorator(AbstractEquipment equipment)
{
_equipment = equipment;
}
public override void Attack()
{
_equipment.Attack();
}
}

一旦业务类需要添加新功能,只需要继承上面的装饰器基类,加上新功能即可,例如:为装备添加强化的功能

     public class EquipmentStrengthenDecorator:BaseEquipmentDecorator
{
//调用直接父类的指定构造函数
public EquipmentStrengthenDecorator(AbstractEquipment equipment)
:base(equipment)
{ }
public override void Attack()
{
base.Attack();
Strengthen();
}
public void Strengthen()
{
Console.WriteLine("武器被强化");
}
}

调用:

    class Program
{
static void Main(string[] args)
{
AbstractEquipment gun = new Gun();
gun = new EquipmentStrengthenDecorator(gun);
gun.Attack();
Console.ReadKey();
}
}

打印:

用枪攻击

武器被强化

这样,强化的功能就添加到了装备之中了

通过继承加组合的装饰器模式,我们可以灵活的动态添加对象的功能职责

装饰器模式类图

装饰器模式4种角色:

抽象业务角色(AbstractEquipment):具体业务类的抽象;

具体业务角色(Gun,Sword):具体业务类,被装饰的直接对象;

装饰器基类角色(BaseEquipmentDecorator):具体装饰器的基类;

具体装饰器角色(EquipmentStrengthenDecorator):提供具体的功能去装饰具体业务角色;

装饰器模式优缺点及使用场景

优点:灵活,扩展性好,能够在不影响业务类的前提下,动态的为其添加本身不存在的功能

缺点:增加了程序的复杂程度

使用场景:为具体的业务对象附加功能职责,例如上述的游戏装备,以及培训班的各层vip,商场的多重优惠等等

出自:博客园-半路独行

原文地址:https://www.cnblogs.com/banluduxing/p/9152453.html

本文出自于http://www.cnblogs.com/banluduxing 转载请注明出处。

代码地址:https://github.com/weiweu/My-space/tree/master/Design/DecoratorPattern

c#设计模式之装饰器模式(Decorator Pattern)的更多相关文章

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

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

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

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

  3. 【UE4 设计模式】装饰器模式 Decorator Pattern

    概述 描述 动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活.是一种对象结构型模式. 套路 抽象构件(Component) 具体构 ...

  4. 设计模式学习--装饰者模式(Decorator Pattern)

    概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...

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

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

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

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

  7. C#设计模式之装饰者模式(Decorator Pattern)

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

  8. php装饰器模式(decorator pattern)

    十一点了. <?php /* The decorator pattern allows behavior to be added to an individual object instance ...

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

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

随机推荐

  1. canvas变换

    canvas变换 方法 save() 保存canvas状态 restore() 回复canvas保存的状态 translate(x, y) 移动canvas位置 rotate(radians) 顺时针 ...

  2. All sentinels down, cannot determine where is mymaster master is running...

    修改配置的哨兵文件 vim /sentinel.conf 将保护模式关闭

  3. 十、api自动化环境问题及解决方案汇总(持续更新)

    1.jenkins报错: Unable to read /root/.jenkins/config.xml at hudson.WebAppMain$3.run(WebAppMain.java:248 ...

  4. TCP接入层的负载均衡、高可用、扩展性架构

    一.web-server的负载均衡 互联网架构中,web-server接入一般使用nginx来做反向代理,实施负载均衡.整个架构分三层: 上游调用层,一般是browser或者APP 中间反向代理层,n ...

  5. UNITY polygon collider不随物体旋转

    U3D中的一般包围框如 boxcollider, meshcollider, capsule collider等都会随物体旋转而旋转.然而polygon collider却不会. 补充:原来所有2D包 ...

  6. SpringMVC 中xml 配置多数据源

    1,配置jdbc.properties jdbc.driver_one=... jdbc.url_one=..... jdbc.username_one=... jdbc.password_one=. ...

  7. 取出资源文件中的bitmap,并将其保存到TMemoryStream中,从资源里载入图象而不丢失调色板

    从资源里载入图象而不丢失调色板 procedure loadgraphic(naam:string);var  { I've moved these in here, so they exist on ...

  8. mac 下 python链接mysql

    安装过程 :http://blog.topspeedsnail.com/archives/6018 注意 报错的话要先装一个东西 http://cdn.mysql.com/Downloads/Conn ...

  9. ORM是什么?如何理解ORM?

    一.ORM简介         对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术.简单的说,ORM是通过使 ...

  10. 131. Palindrome Partitioning (Back-Track, DP)

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...