Edited at

Angular の Service, Factory, Value, Constant, Provider の違いって?

More than 5 years have passed since last update.

Angular 勉強中なのですが、公式ドキュメントの Provider のところを読んでやっとわかったのでメモしておきます。


  • Service には二つの意味がある。一つは、DI 対象のうち、書く人が API を決められるもの。もう一つは、DI 対象の Object の作り方(Provider Recipe)のうちの一つ service()


  • factory() でできる Object も Service。

  • Service(二つ目の意味), Factory, Value, Constant, Provider は DI 対象 Object の作り方の名前。

  • よくわからなければ factory() を使う。service() の中で return しているなら、factory() を使うべき。


だいたいみんな Service

Angular には Service や Factory というものが存在して、それぞれ service()factory() で作られ、微妙に役割が違うものなのだと思っていました。ところが、公式ドキュメントによれば、これらで できるものは全て ServiceService や Factory というのは作り方の問題 だったのです。

DI 対象の Object は以下の二つに分けられるそうです。


  • Specialized Object: Controller, Directive, Filter, Animation のように、API がフレームワークによって決まっているもの。

  • Service: Specialized Object でないもの。つまり、書く人が API を自由に決められるもの。

そう、つまり Controller/Directive/Filter/Animation 以外はみんな Service だったのです。数値や文字列などのプリミティブも登録できるので、これらも Service と呼べるかは疑問ですが・・・。

なので、ある程度以上の規模の開発になると、Service の中でもグループ分けをする必要がありそうです。


Provider Recipe

では、service(), factory(), value(), constant(), provider() の違いって何なの?というと、これらは Service や Specialized Object の作り方(Provider Recipe と呼ばれています)の名前です。(Service という言葉に二つの意味があることになり、紛らわしいですね。公式ドキュメントにも「子供に Child という名前をつけたようなもので、この命名には後悔している」と書いてあります。)

この 5 つは、渡した値がそのまま使われるものと、渡した関数を実行した結果が使われるものに分けることができます。


渡した値がそのまま使われるやつ


  • Value Recipe: 一番単純なやつで、渡した Object またはプリミティブがそのまま使われます。

  • Constant Recipe: 大体 Value Recipe と一緒ですが、アプリの Config フェーズで利用することができます。

普通は Value Recipe を使っておけばいいんじゃないでしょうか。


渡した関数の実行結果が使われるやつ


  • Factory Recipe: 渡した関数のを普通に実行した結果が使われます。関数の引数を使って DI ができます。

  • Service Recipe: 渡した関数をコンストラクタとして new した結果が使われます(実装はちょっと違うそうですが、振る舞いはだいたいそんな感じのようです)。コンストラクタの引数を使って DI ができます。

  • Provider Recipe: 一番ローレベルなやつです。Factory Recipe + アプリ毎の設定が可能です。

普通は Factory Recipe を使っておけばいいんじゃないでしょうか。

Service を作りたいので .service() を使う、というのは多くの場合間違いです。特に .service() に渡す関数の中で return している場合は、コンストラクタの意味がないので .factory() を使うべきでしょう。

どうせ DI 対象のほとんど(Controller 以外)は Singleton なので、コンストラクタを使う意味は特にないと思っています。


Specialized Object で使われる Recipe

自分で書く Service には好きな Recipe を選ぶことができます。では、Specialized Object にはどの Recipe が使われるでしょうか?


  • Controller 以外: Factory Recipe です。

  • Controller: ほぼ Service Recipe ですが、必要に応じて複数回インスタンス化されるところが違います。