• 设计模式之装饰器模式


     

    装饰器模式简介

    装饰器模式是动态的向一个对象添加新的功能,并且保持其类方法签名的完整性,换言之,其方法及继承结构将不会被改变。这种模式一种结构型模式,是对现有类的包装。这种模式,比生成子类更加灵活,更重要的是,装饰者模式装饰的是特定的行为或者或是职责,也没有必要通过子类实现。

    在日常生活中,装饰器模式的场景更多是的打扮了,一个妹子,嫌弃自己的脸长得不够漂亮,想换张脸很困难,但是化化妆还是很容易的(当然了,化妆也分男女的,此处指的是女士化妆,大老爷们有啥好化的,还不如收拾山河,收复钓鱼岛),加点粉底啊,涂点腮红啊,涂眼影,画眼线,再加点口红,哇塞,一个大美女就这样诞生了,这就是打扮的力量,这就是装饰的力量,这也是爱美的力量。写到这里我突然想到一句话就是,清水出芙蓉,天然去雕饰,当自然不能使之完美时,艺术使之完美。

    装饰器模式就是,在一个已经先天不足或者未来有可能需要扩展的场景中,修改代码将是一件工作量十分巨大的事情,也是危险系数比较高的事情,我们需要以一个比较经济、安全的方式来解决这个问题,可以认为是从周边方式、从外围方式来解决问题。

    这个例子也告诉我们,生活处处是学问,纸上得来终觉浅,觉知此时要躬行,当你看到这篇文章的时候,不必太过纠结于其定义或者UML,你可以更多的去类比你的生活,这样你会更快更深刻的获取知识。

    装饰器模式UML类图

    zhuangshiqi

    小提醒

    装饰器类继承并依赖于更抽象一级的IWoman接口,在地位上与Face、Clothes一致
    装饰器类对IWoman接口的方法进行了包装,隐隐约约有模板方法模式的影子

    范例

    以下范例,会使用前面所说的女人喜欢打扮使用打扮方式解决自然问题或者说更进一层楼的问题,女人的打扮有方方面面的,不过最常见也就是化妆和穿衣,所以此处使用这两个装扮方式予以Coding。

    抽象接口:

       1:  public interface IWoman
       2:  {
       3:      void Attire();
       4:  }

     

    脸部打扮

       1:  public class Face : IWoman
       2:  {
       3:      public void Attire()
       4:      {
       5:          Console.Write("那些年还不会打扮,擦点自己也不知道是什么的粉");
       6:      }
       7:  }

    穿衣打扮

       1:  public class Clothes : IWoman
       2:  {
       3:      public void Attire()
       4:      {
       5:          Console.Write("那些年还不会打扮,穿点屌丝装");
       6:      }
       7:  }

    装饰器抽象类

       1:  public abstract class RougeDecorator : IWoman
       2:  {
       3:      protected IWoman woman;
       4:   
       5:      public RougeDecorator(IWoman woman)
       6:      {
       7:          this.woman = woman;
       8:      }
       9:   
      10:      public virtual void Attire()
      11:      {
      12:          this.woman.Attire();
      13:      }
      14:  }

    脸部增加装饰

       1:  public class FaceDecorator : RougeDecorator
       2:  {
       3:      public FaceDecorator(IWoman woman) : base(woman)
       4:      {
       5:      }
       6:   
       7:      public override void Attire()
       8:      {
       9:          this.woman.Attire();
      10:          Console.WriteLine("这些年学会了打扮,还要继续化妆,涂眼影,画眼线");
      11:      }
      12:  }

    穿衣增加装饰

       1:  public class ClothesDecorator : RougeDecorator
       2:  {
       3:      public ClothesDecorator(IWoman woman) : base(woman)
       4:      {
       5:      }
       6:   
       7:      public override void Attire()
       8:      {
       9:          this.woman.Attire();
      10:          Console.WriteLine("这些年学会了打扮,打底裤,包臀裙,上衣也要换一下,名牌穿起,还要再戴个帽子,回头率必须杠杠的");
      11:      }
      12:  }

    调用

       1:  class Program
       2:  {
       3:      static void Main(string[] args)
       4:      {
       5:          IWoman womanFace = new Face();
       6:          IWoman womanDress = new Clothes();
       7:   
       8:          IWoman womanFaceDecorator = new FaceDecorator(womanFace);
       9:          IWoman womanClothesDecorator = new ClothesDecorator(womanDress);
      10:   
      11:          womanFaceDecorator.Attire();
      12:          womanClothesDecorator.Attire();
      13:   
      14:          Console.WriteLine("----------------------------------------------------");
      15:          Console.WriteLine("完美女人出现了");
      16:          Console.WriteLine("既然完美女人已经出现了,那就抓紧娶回家,然后把装饰器给关掉");
      17:          Console.WriteLine("卧槽,貌似有点难关呀,该死的装饰器");
      18:          Console.WriteLine("难不倒我,把你化妆品换成路摊货,越涂越难看,哈哈,难不倒我程序员");
      19:   
      20:          Console.ReadLine();
      21:      }
      22:  }

    调用结果如下图所示

    1553947981(1)

    装饰器模式优缺点

    优点:

    • 很好的利用了开闭原则,装饰类和被装饰类可以独立发展,不会相互耦合。
    • 装饰模式是继承的一个替代模式,可以动态扩展一个实现类的功能

    缺点:

    • 装饰模式会使得业务及代码变得复杂

    装饰器模式使用场景思考

    装饰器模式,从某种角度上说,可能更适合用于对已经成型的业务进行修改的场景,不管是用于动态扩展,还是动态移除,装饰器都能很方便的胜任对对象的修改操作。另外就是,继承也可以解决类似问题,但是装饰器可以更好的扩展,因为,我们一般解决的是特定对象的特定行为,而不会对整个对象进行修改,这样子跟大型重构没有什么区别。所以,特定场景的修改,装饰器来的更快,更简单,更有效率,没有必要兴师动众。

  • 相关阅读:
    我不写博客的原因就是cnblogs不好用
    使用KeePass愉快的来管理你的密码
    Visual studio常用的code snippets
    日常工作小贴士
    win10下面visual studio, sublime ctrl+shift+f快捷键失效的原因
    Markdown常用语法对应
    常见的Message Queue应用场景
    二分查找(binary search)
    在ROS中使用花生壳的域名服务
    排序算法 选择排序(selection sort)
  • 原文地址:https://www.cnblogs.com/edison0621/p/10628782.html
Copyright © 2020-2023  润新知