最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 精读《设计模式 - Decorator 装饰器模式》

    正文概述 掘金(黄子毅)   2020-11-30   365

    Decorator(装饰器模式)

    Decorator(装饰器模式)属于结构型模式,是一种拓展对象额外功能的设计模式,别名 wrapper

    意图:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。

    举例子

    如果看不懂上面的意图介绍,没有关系,设计模式需要在日常工作里用起来,结合例子可以加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。

    相框

    照片 + 相框 = 带相框的照片,这背后就是一种装饰器模式:照片具有看的功能,相框具有装饰功能,在你看照片的基础上,还能看到精心设计的相框,增加了美感,同时相框还可以增加照片的保存时间与安全性。

    相框与照片是一种组合关系,任何照片都可以放到相框中,而不是每个照片生成一个特定的相框,显然,组合的方式更加灵活。

    带有缓存的文件读写

    假设我们有一个类 FileIO 用来读写文件,但是没有缓存能力,此时是新建一个 CachedFileIO 子类好,还是创建一个 CachedIO?

    一眼看上去好像 CachedFileIO 用起来更方便,而 CachedIO 的用法是 new CachedIO(new FileIO()) 稍微麻烦一些,但如果我们增加一个网络读写类 NetworkIO,一个数据库读写类 DBIO 呢?

    显然,继承的方式会使子类数量极速膨胀,而组合的方式则非常灵活,生成一个支持缓存的网络读写器,只需要 new CachedIO(new NetworkIO()) 即可,这就是组合灵活的地方。

    当然,为了实现这个能力,CachedIO 需要与 FileIOCachedFileIOCachedIO 继承自同一个类,具备相同的接口。

    搭建平台的组件 wrapper

    装饰器模式别名也叫 wrapperwrapper 也经常在前端搭建场景中遇到,当搭建平台加载一个组件时,希望拓展其基础能力,一般会使用 wrapper 层对组件进行嵌套,wrapper 层就是在不改变 API 的基础上,对第三方组件进行增强。

    意图解释

    意图:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。

    不同于继承,组合可以在运行时进行,所以称之为 “动态添加”,这里的 “额外职责” 泛指一切功能,比如在按钮点击时进行一些 log 日志的打印,在绘制 text 文本框时,额外绘制一个滚动条和边框等等。

    “就增加功能来说,Decorator 模式相比生成子类更为灵活” 这句话的含义是,组合比继承更灵活,当可拓展的功能很多时,继承方案会产生大量的子类,而组合可以提前写好处理函数,在需要时动态构造,显然是更灵活的。

    结构图

    精读《设计模式 - Decorator 装饰器模式》

    ConcreteComponent 指的是需要被装饰的组件,可以看到,装饰器 Decorator 与他都继承同一个类,这样能保证 API 的一致,才保证无论装饰多少层,始终符合 Component 类型。

    装饰器如果有多种,就要将 Decorator 申明为抽象类,ConcreteDecoratorAConcreteDecoratorB 分别实现它们,如果只有一种装饰器,可以退化到 Decorator 自身就是一种实现。

    代码例子

    下面例子使用 typescript 编写。

    class Component {
      // 具有点击事件
      public onClick = () => {}
    }

    class Decorator extends Component {
      private _component

      constructor(component) {
        this._component = component
      }

      public onClick = () => {
        log('打点')
        this._component.onClick()
      }
    }

    const component = new Component()
    // 一个普通的点击
    component.onClick()

    const wrapperComponent = new Decorator(component)
    // 一个具有打点功能的点击
    wrapperComponent.onClick()

    其实方法很简单,通过组合,我们得到了一个能力更强的组件,而实现的方式就是利用构造函数保存组件实例,并在复写函数时,增加一些增强实现。

    弊端

    装饰器的问题也是组合的问题,过多的组合会导致:

    • 组合过程的复杂,要生成过多的对象。
    • 包装器层次增多,会增加调试成本,我们比较难追溯到一个 bug 是在哪一层包装导致的。

    总结

    装饰器模式是非常常用的模式,Decorator 是一个透明的包装,只要保证包装的透明性,就可以最大限度发挥装饰器模式的优势。

    最后总结一个装饰器应用图:

    精读《设计模式 - Decorator 装饰器模式》

    讨论地址是:精读《设计模式 - Decorator 装饰器模式》· Issue #286 · dt-fe/weekly

    如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

    关注 前端精读微信公众号

    精读《设计模式 - Decorator 装饰器模式》

    版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)


    起源地下载网 » 精读《设计模式 - Decorator 装饰器模式》

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元