• 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

  • 相关阅读:
    洛谷
    洛谷
    NOIP 普及组 2014 螺旋矩阵
    NOIP 普及组 2014 珠心算测验
    hdu 1114Piggy-Bank(完全背包)
    hdu 2059龟兔赛跑("01"背包)
    洛谷 P1282 多米诺骨牌("01"背包)
    洛谷 P1140 相似基因(DP)
    洛谷 P1880 [NOI1995] 石子合并(区间DP)
    洛谷 P1280 尼克的任务
  • 原文地址:https://www.cnblogs.com/banluduxing/p/9152453.html
Copyright © 2020-2023  润新知