【问题标题】:What are "decorators" and how are they used?什么是“装饰器”,它们是如何使用的?
【发布时间】:2013-04-11 03:45:16
【问题描述】:

我很好奇 AngularJS 中的装饰器到底是什么。除了AngularJS documentation 中的简介和youtube video 中的简短(尽管很有趣)提及之外,没有太多关于装饰者的在线信息。

正如 Angular 人所说,装饰器是:

服务的装饰,允许装饰器拦截服务 实例创建。返回的实例可能是原始实例, 或委托给原始实例的新实例。

我真的不知道是什么意思,而且我不确定你为什么要将这个逻辑与服务本身分开。例如,如果我想在不同的条件下返回不同的东西,我只需将不同的参数传递给相关函数或使用另一个函数共享该私有状态。

我还是个 AngularJS 菜鸟,所以我确信这只是我的无知和/或坏习惯。

【问题讨论】:

    标签: javascript angularjs decorator angularjs-decorator


    【解决方案1】:

    装饰器允许我们分离横切关注点并允许服务保留单一职责原则,而无需担心“基础设施”代码。

    装饰器的实际用途:

    • 缓存:如果我们的服务可能会进行昂贵的 HTTP 调用,我们可以将服务包装在缓存装饰器中,该装饰器会在进行外部调用之前检查本地存储。
    • 调试/跟踪:根据您的开发/生产配置进行切换,使用调试或跟踪包装器装饰您的服务。
    • 限制:将频繁触发的调用包装在去抖动包装器中。例如,让我们能够轻松地与速率受限的服务进行交互。

    在所有这些情况下,我们将服务中的代码限制为其主要职责。

    【讨论】:

      【解决方案2】:

      简而言之,装饰器可以描述如下:-

      装饰器函数拦截服务的创建,允许它 覆盖或修改服务的行为。

      它通过角度使用$provide服务并修改或替换另一个服务的实现

      $provide.decorator('service to decorate',['$delegate', function($delegate) {
        // $delegate - The original service instance, 
        //             which can be replaced, monkey patched, 
        //             configured, decorated or delegated to. 
        //             ie here what is there in the 'service to decorate'
      
        //   This function will be invoked, 
        //   when the service needs to be provided 
        //   and should return the decorated service instance.
        return $delegate;
      }]);
      

      例子:

      $provide.decorator('$log', ['$delegate', function($delegate) {
        // This will change implementation of log.war to log.error
        $delegate.warn = $delegate.error; 
        return $delegate;
      }]);
      

      应用程序

      除了@JBland 的回答。

      • 应用范围的区域设置:-

        你可以找到一个例子here

      • 通过角度服务更改服务的默认行为和现有实现:-

        您可以找到一个示例here

      • 函数在不同环境中的切换行为。

      【讨论】:

        【解决方案3】:

        简单来说,我们可以说它就像一个扩展方法。对于前。我们有一个类,它有两个方法,在运行时我们想在其中添加更多方法,然后我们使用装饰器。

        我们不能将 $provide.decorator 与常量一起使用,因为我们无法更改它们正在提升只读属性的常量。

        【讨论】:

          【解决方案4】:

          $provide.decorator 的一个很好的用例是当您需要对您的模块所依赖的某些第三方/上游服务进行较小的“调整”,同时保持服务完好无损(因为您不是所有者/维护者服务)。 Here 是 plunkr 上的演示。

          【讨论】:

          • 很棒的例子。我实际上想知道如何在不干涉第三方模块功能的情况下扩展它们
          • 装饰器是否真的对服务的所有实例进行了类型化,或者它们是否仅限于装饰它们的模块?换句话说,假设我有一个模块 A,它装饰了模块 B 的服务。然后我有模块 C,它依赖于模块 A 和模块 B。在模块 C 内部,来自模块 B 的服务是原始版本还是修饰版本?跨度>
          • @JonJaques - 这是一个很好的问题。我没有遇到过这样的情况。如果我猜的话,模块 C 看到的服务版本应该是来自模块 A 的修饰版本,但在我自己尝试之前我不能肯定地说。你为什么不写一个简单的 plunkr/jsffidle 并尝试一下。如果您能与我们分享您的发现,那就太好了。干杯。
          • @JonJaques - 无法抑制我的好奇心,所以我在原始示例中添加了几行代码来找到您问题的答案,link。总之,我之前评论的猜测是对的。
          • 工厂、服务等都是单例的(因为它们是提供的),所以一旦装饰,总是装饰。
          【解决方案5】:

          decorator 可以拦截factory, service, value, provider 创建的服务实例,并提供更改一些instance(service) 的选项,否则这些instance(service) 是不可配置的/带有选项。

          它还可以提供模拟实例用于测试目的,例如$http

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-06
          • 1970-01-01
          • 2016-11-25
          • 1970-01-01
          • 1970-01-01
          • 2013-12-27
          • 2013-01-12
          • 2011-10-08
          相关资源
          最近更新 更多