半路独行

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

引子

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

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

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

 1  public abstract class AbstractEquipment
 2     {
 3         public int Id { get; set; }
 4 
 5         public string Name { get; set; }
 6 
 7         public abstract void Attack();
 8     }
 9 
10     public class Gun : AbstractEquipment
11     {
12         public override void Attack()
13         {
14             Console.WriteLine("用枪攻击");
15         }
16     }
17 
18     class Sword : AbstractEquipment
19     {
20         public override void Attack()
21         {
22             Console.WriteLine("用剑攻击");
23         }
24     }

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

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

 1   //继承
 2     public class GunInherit:Gun
 3     {
 4         public override void Attack()
 5         {
 6             base.Attack();
 7             Console.WriteLine("善恶值增加");
 8         }
 9     }
10     
11     //组合
12     public class EquipmentCombination
13     {
14         private AbstractEquipment _equipment = null;
15         public EquipmentCombination(AbstractEquipment equipment)
16         {
17             _equipment = equipment;
18         }
19 
20         public void Attack()
21         {
22             _equipment.Attack();
23             Console.WriteLine("善恶值增加");
24         }
25     }

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

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

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

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

 装饰器模式

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

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

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

 1      public class BaseEquipmentDecorator : AbstractEquipment
 2     {
 3         private AbstractEquipment _equipment = null;
 4         public BaseEquipmentDecorator(AbstractEquipment equipment)
 5         {
 6             _equipment = equipment;
 7         }
 8         public override void Attack()
 9         {
10             _equipment.Attack();
11         }
12     }

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

 1     public class EquipmentStrengthenDecorator:BaseEquipmentDecorator
 2     {
 3         //调用直接父类的指定构造函数
 4         public EquipmentStrengthenDecorator(AbstractEquipment equipment)
 5             :base(equipment)
 6         {
 7 
 8         }
 9         public override void Attack()
10         {
11             base.Attack();
12             Strengthen();
13         }
14         public void Strengthen()
15         {
16             Console.WriteLine("武器被强化");
17         }
18     }

调用:

    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

posted @ 2018-06-10 17:46  半路独行  阅读(7416)  评论(0编辑  收藏  举报