2013-04-18 71 views
139

我很好奇AngularJS中的装饰器究竟是什么。除了AngularJS documentation中的简短内容以及youtube video中提到的一个简短(虽然有趣)的提及之外,没有太多关于装饰者的信息。什么是“装饰者”,它们是如何使用的?

由于角的家伙把它放在装饰是:

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

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

我还是一个AngularJS noob,所以我敢肯定这只是我已经拿起的无知和/或不良习惯。

回答

211

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

+5

很好的例子。我真的想知道如何扩展第三方模块的功能而不用插手他们 – 2014-01-29 14:30:03

+5

装饰者是否实际上鸭子服务的所有实例,还是仅限于装饰它们的模块?换句话说,假设我有模块A来装饰模块B的服务。然后我有模块C,它依赖于模块A和模块B.在模块C内部,模块B的服务是原始还是装饰版本? – 2014-02-26 23:32:22

+2

@JonJaques - 这是一个很好的问题。我没有遇到过这种情况。如果我猜测,模块C所看到的服务版本应该是模块A中的服务版本,但我不能肯定地说,直到我自己尝试。你为什么不写一个简单的plunkr/jsffidle并对其进行实验。如果你能和我们分享你的发现,那将是非常棒的。干杯。 – tamakisquare 2014-02-28 22:32:02

63

装饰者使我们能够分离出横切关注点,并允许服务保持单一责任原则而不用担心“基础结构”代码。

实用装饰的用途:

  • 缓存:如果我们有一个服务,这使得潜在的昂贵HTTP调用,我们可以在一个缓存装饰这使得外部调用之前检查本地存储包裹服务。
  • 调试/追踪:根据您的开发/生产配置使用调试或跟踪包装来装饰您的服务。
  • 节流:将经常触发的调用包装在去抖动包装中。例如,允许我们轻松地与速率限制的服务进行交互。

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

10

decorator可以拦截factory, service, value, provider创建服务实例,并给出了选项来改变一些instance(service)是不是另有配置/选项使用。

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

+1

值得注意的是,你也可以覆盖'指令'的定义为[由Ben Nadel提供](http://www.bennadel.com/?site-photo=490) – 2016-07-05 12:00:23

+0

这里是参考官方的Angular文档:[https://docs.angularjs.org/guide/decorators](https://docs.angularjs.org/guide/decorators) – 2016-07-05 12:51:05

3

简而言之,我们可以说它就像一个扩展方法。例如。我们有一个类,它有两个方法,运行时我们想添加更多的方法,然后我们使用装饰器。

我们不能使用带有常量的$ provide.decorator,因为我们无法更改它们正在堆叠的只读属性的常量。

1

总之装饰可被描述为如下: -

装饰器功能截取服务的创建,允许它 重写或修改服务的行为。

它通过角使用$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

  • 的Changiging默认行为,现有的实现由角服务的服务的: -

    你可以找到实例here

  • 切换行为或不同环境中的功能。

相关问题