2013-04-18 47 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

  • 切換行爲或不同環境中的功能。

相關問題