「デコレータ」とは何ですか?


148

AngularJSのデコレーターの正確なところを知りたいです。AngularJSのドキュメント言い訳や、YouTubeビデオでの(興味深いものの)簡単な言及を除いて、デコレーターのためのオンラインの情報はあまりありません。

Angularの連中が言うように、デコレータは次のとおりです。

サービスの装飾。デコレータがサービスインスタンスの作成をインターセプトできるようにします。返されるインスタンスは、元のインスタンスか、元のインスタンスに委任された新しいインスタンスです。

それが何を意味するのか本当にわかりませんし、なぜこのロジックをサービス自体から切り離すのかわかりません。たとえば、異なる条件下で異なるものを返したい場合は、関連する関数に異なる引数を渡すか、そのプライベート状態を共有する別の関数を使用します。

私はまだAngularJSの初心者なので、私が気付いたのは単に無知や悪い習慣だと思います。

回答:


219

の良いユースケースは$provide.decorator、サービスを変更せずに(サービスの所有者/保守者ではないため)、モジュールが依存するサードパーティ/アップストリームサービスに小さな「微調整」を行う必要がある場合です。これはplunkrのデモです。


6
素晴らしい例。サードパーティのモジュールの機能をいじらずに拡張する方法を実際に考えていました
Arthur Kovacs

5
デコレータは実際にサービスのすべてのインスタンスをダックタイプしますか、それともそれらをデコレートするモジュールだけにスコープを設定していますか?つまり、モジュールBのサービスを装飾するモジュールAがあるとします。次に、モジュールAとモジュールBに依存するモジュールCがあります。モジュールCの内部では、モジュールBのサービスは元のバージョンですか、それとも装飾されたバージョンですか?
Jon Jaques 14

3
@JonJaques-それは素晴らしい質問です。私はそのような状況に遭遇したことはありません。推測すると、モジュールCが認識するサービスのバージョンは、モジュールAの装飾されたものであるはずですが、自分で試してみるまでは、確実にそれを言うことはできません。簡単なplunkr / jsffidleを書いて、それを試してみませんか。あなたが私たちとあなたの発見を共有することができればそれは素晴らしいでしょう。乾杯。
tamakisquare 2014

6
@JonJaquesは-私はあなたの質問に対する答えを見つけるために私の元の例に数行を追加しましたので、私の好奇心を押したままにできませんでしたリンクを。要するに、私の前のコメントでの推測は正しいです。
tamakisquare 2014

17
工場、サービスなどは(提供されているとおり)シングルトンであるため、一度装飾されると常に装飾されます。
FlavorScape

66

デコレータを使用すると、横断的な関心事を分離し、サービスが「インフラストラクチャ」コードを気にすることなく単一の責任の原則を維持できるようになります。

デコレーターの実用的な使用:

  • キャッシング:潜在的に高額なHTTP呼び出しを行うサービスがある場合、外部呼び出しを行う前にローカルストレージをチェックするキャッシングデコレータでサービスをラップできます。
  • デバッグ/トレーシング:開発/プロダクション構成に応じて、デバッグまたはトレーシングラッパーでサービスを装飾するスイッチがあります。
  • スロットル:頻繁にトリガーされる呼び出しをデバウンスラッパーでラップします。たとえば、レート制限されたサービスと簡単にやり取りできます。

これらすべての場合において、サービスのコードをその主な責任に制限します。


10

decoratorfactory, service, value, provider、によって作成されたサービスインスタンスを傍受でき、オプションでinstance(service)/で設定できないサービスを変更するオプションを提供します。

たとえば、テスト目的でモックアップインスタンスを提供することもできます$http


1
Ben Nadelによって提示されたdirective定義を上書きすることもできます
David Salamon 2016

これは公式のAngularドキュメントのリファレンスです:https
David Salamon

3

簡単に言うと、これは拡張メソッドのようなものです。例:クラスがあり、2つのメソッドがあり、実行時にメソッドを追加したい場合は、Decoratorを使用します。

$ 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の回答に加えて。

  • アプリケーション全体のロケール設定:-

    ここで例を見つけることができます

  • 角度サービスによるサービスのデフォルト動作と既存の実装の変更:-

    あなたはここにサンプルを見つけることができます

  • 異なる環境での関数の動作の切り替え。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.