AngularJS:ファクトリの代わりにサービスを使用する場合


296

ここで我慢してください。AngularJS:サービスvsプロバイダーvsファクトリーのような他の答えがあることを知っています。

しかし、いつ工場でサービスを利用するかはまだわかりません。

ファクトリーは、複数のコントローラーから呼び出すことができる「共通の」関数を作成するために一般的に使用されていることがわかります。共通のコントローラー関数の作成

Angularのドキュメントはサービスよりもファクトリを好むようです。さらに混乱を招くファクトリーを使用するとき、彼らは「サービス」にさえ言及します!http://docs.angularjs.org/guide/dev_guide.services.creating_services

では、いつサービスを利用するのでしょうか?

サービスでしかできない、またははるかに簡単なことはありますか?

舞台裏で起こっている何か違うことはありますか?パフォーマンス/メモリの違い?

ここに例があります。宣言の方法を除いて、それらは同じように見え、なぜ私が一方を他方に対して行うのか理解できません。http://jsfiddle.net/uEpkE/

更新: Thomasの回答から、サービスがより単純なロジック用であり、プライベートメソッドを使用したより複雑なロジック用のファクトリーであることが示唆されているため、以下のフィドルコードを更新し、どちらもプライベート関数をサポートできるようです?

myApp.factory('fooFactory', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo; }

    return {
        setFoobar: function(foo){
            addHi(foo);
        },
        getFoobar:function(){
            return fooVar;
        }
    };
});
myApp.service('fooService', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo;}

    this.setFoobar = function(foo){
        addHi(foo);
    }
    this.getFoobar = function(){
        return fooVar;
    }
});

function MyCtrl($scope, fooService, fooFactory) {
    fooFactory.setFoobar("fooFactory");
    fooService.setFoobar("fooService");
    //foobars = "Hi fooFactory, Hi fooService"
    $scope.foobars = [
        fooFactory.getFoobar(),
        fooService.getFoobar()
    ];
}

もちろん、サービスはプライベートをサポートしますが、私の投稿を正しく読んだ場合、それは純粋にコードスタイルです。「プライベート」変数をシミュレートするために、新しい字句スコープを利用することもできます。それは「シミュレーション」です
トーマス・ポンズ

この議論は非常に便利なI見つけるstackoverflow.com/questions/15666048/...
アナンド・グプタ

回答:


280

説明

ここにはさまざまなものが含まれています。

最初:

  • サービスを使用する場合、関数のインスタンス( " this"キーワード)を取得します
  • ファクトリを使用する場合は、関数参照(ファクトリのreturnステートメント)を呼び出すことによって返される値を取得 します

ref: angular.service対angular.factory

第二:

AngularJSのすべてのプロバイダー(値、定数、サービス、ファクトリー)はシングルトンです。

第三:

どちらか(サービスまたはファクトリー)を使用するのは、コードスタイルに関するものです。ただし、AngularJS での一般的な方法は、factoryを使用することです。

どうして ?

ので 「ファクトリメソッドはAngularJS依存性注入システムにオブジェクトを取得する最も一般的な方法です。それは非常に柔軟性があり、洗練された作成ロジックを含めることができます。工場は定期的に機能しているので、我々はまた、シミュレートするために、新しいレキシカルスコープを活用することができ、」プライベート「変数。特定のサービスの実装の詳細を非表示にできるため、これは非常に便利です。」

参照http : //www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821)。


使用法

サービス:()注入された関数参照に追加するだけで起動できるユーティリティ関数を共有するのに役立ちます。injectedArg.call(this)または同様に実行することもできます。

ファクトリー:インスタンスを作成するために新規作成できる「クラス」関数を返すのに役立ちます。

そのため、サービスに複雑なロジックがあり、この複雑さを公開したくない場合は、ファクトリを使用します。

その他の場合、サービスのインスタンスを返したい場合はserviceを使用してください

しかし、時間の経過とともに、ファクトリーを80%のケースで使用するようになると思います。

詳細:http : //blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


更新:

ここに優れた投稿:http : //iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

通常の関数のように関数を呼び出す場合は、factoryを使用 します。new演算子を使用して関数をインスタンス化する場合は、serviceを使用してください。違いがわからない場合は、factoryを使用してください。」


更新:

AngularJSチームが彼の仕事をして説明をします:http : //docs.angularjs.org/guide/providers

そしてこのページから:

「ファクトリーとサービスは最も一般的に使用されるレシピです。それらの唯一の違いは、ファクトリーがJavaScriptプリミティブと関数を生成できるのに対して、サービスレシピはカスタムタイプのオブジェクトに適しているということです。」


7
再第一:私はそれをどこでも読んだが、それの実際的な意味を理解していない。私はあなたの答えから「大部分」実際的な違いはないと思いますか?本のリファレンスをありがとう!
user1941747 2013

サービスが本当に複雑で、プライベートメソッドとオブジェクトがファクトリを使用する必要がある場合は簡単です
Thomas Pons

1
「サービスのインスタンスを返す場合は、serviceを使用する」と追加したことに気付きました。私のフォローアップの質問は、いつサービスのインスタンスを返したいですか?ここで特定のユースケースを見つけようとしています。
user1941747 2013

12
「ファクトリーは通常の関数なので、新しいレキシカルスコープを利用して「プライベート」変数をシミュレートすることもできます。」-これは工場に固有のものではなく、サービスでも同じことができます。
pootzko

Googleチームは工場よりもサービスを好むようです。これにより状況がさらに混乱します。 google-styleguide.googlecode.com/svn/trunk/…– xzhang 2015
1

111

allernhwkimは当初、この質問への回答自分のブログにリンクして投稿していましたが、モデレーターが削除しました。これは、サービス、プロバイダー、およびファクトリーで同じことを行う方法を説明するだけでなく、ファクトリーでは実行できないプロバイダーで実行できること、およびサービスではできない工場。

彼のブログから直接:

app.service('CarService', function() {
   this.dealer="Bad";
    this.numCylinder = 4;
});

app.factory('CarFactory', function() {
    return function(numCylinder) {
      this.dealer="Bad";
        this.numCylinder = numCylinder
    };
});

app.provider('CarProvider', function() {
    this.dealerName = 'Bad';
    this.$get = function() {
        return function(numCylinder) {
            this.numCylinder = numCylinder;
            this.dealer = this.dealerName;
        }
    };
    this.setDealerName = function(str) {
      this.dealerName = str;
    }      
});

これは、CarServiceが常に4気筒の自動車を生産する方法を示しています。個々の自動車用に変更することはできません。一方、CarFactoryは関数を返すのでnew CarFactory、コントローラーで行うことができ、その車に固有のいくつかのシリンダーを渡します。new CarServiceCarServiceは関数ではなくオブジェクトであるため、実行できません。

工場がこのように機能しない理由:

app.factory('CarFactory', function(numCylinder) {
      this.dealer="Bad";
      this.numCylinder = numCylinder
});

そして、インスタンス化する関数を自動的に返します。これは、これを行うことができないためです(プロトタイプなどに追加します)。

app.factory('CarFactory', function() {
    function Car(numCylinder) {
        this.dealer="Bad";
        this.numCylinder = numCylinder
    };
    Car.prototype.breakCylinder = function() {
        this.numCylinder -= 1;
    };
    return Car;
});

それが文字通り自動車を生産する工場である方法を見てください。

彼のブログからの結論はかなり良いです:

結論として、

---------------------------------------------------  
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------  
| Factory | Yes      | Yes          | No          |
---------------------------------------------------  
| Service | Yes      | No           | No          |
---------------------------------------------------  
| Provider| Yes      | Yes          | Yes         |       
---------------------------------------------------  
  1. ハッシュなどの単純なオブジェクト({foo; 1、bar:2}など)だけが必要な場合は、Serviceを使用します。コーディングは簡単ですが、インスタンス化することはできません。

  2. オブジェクト、つまりnew Customer()、new Comment()などをインスタンス化する必要がある場合は、Factoryを使用します。

  3. 構成する必要がある場合は、プロバイダーを使用します。つまり、テストURL、QA URL、製品URL。

ファクトリでオブジェクトを返すだけの場合は、おそらくサービスを使用する必要があります。

これを行わないでください:

app.factory('CarFactory', function() {
    return {
        numCylinder: 4
    };
});

代わりにサービスを使用してください:

app.service('CarService', function() {
    this.numCylinder = 4;
});

11
それは私にとって非常に役に立ちます。+1比較表
Vu Anh 2014

5
1つのパラメーターnumCylinderでサービス関数を定義すると、ファクトリメソッドと同じ柔軟性が得られます
Ovi

この投稿を読んでjavascriptを知っていれば、このブログを読んで時間の無駄を省き、角度を理解してください。この違いを完全に理解できます。
ncubica

4
とても驚いた !ここでブログを参照していますが、どちらもまったく反対のことを言っています。あなたは言う:工場-インスタンス化可能-はいブログは言う:工場-インスタンス化可能-いいえ
Devesh M

1
@Deveshに同意します。インスタンスが混同されていると思います。ブログ投稿から:「ファクトリーのみでは、ファクトリーをインスタンス化できないため、これを達成することはできません」。
マット

20

これらすべてのプロバイダーの概念は、最初に表示されるよりもはるかに単純です。プロバイダーを分析してさまざまな部分を引き出すと、非常に明確になります。

単にこれらのプロバイダのそれぞれをそれを置くためには、このために、他の特殊なバージョンです:provider> factory> value/ constant/service

プロバイダーができることを実行している間は、プロバイダーをチェーンのさらに下で使用できるため、コードの記述が少なくなります。それがあなたが望むものを達成しない場合、あなたは連鎖を上に行くことができ、あなたはただより多くのコードを書かなければならないでしょう。

この画像は私が何を意味しているのかを示しています。この画像では、プロバイダーのコードが表示され、強調表示されている部分が代わりにプロバイダーのどの部分を使用してファクトリー、値などを作成できるかを示しています。

AngularJSプロバイダー、ファクトリー、サービスなどはすべて同じものです
(ソース:simplygoodcode.com

画像を取得したブログ投稿の詳細と例については、http//www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/にアクセスしてください。


8

ファクトリーとサービスの両方により、プロバイダーによって構成され、コントローラーに挿入されてブロックを実行できるシングルトンオブジェクトが生成されます。インジェクティの観点から見ると、オブジェクトが工場からのものかサービスからのものかはまったく同じです。

では、いつファクトリを使用し、いつサービスを使用するのでしょうか。それはあなたのコーディングの好みに要約され、他には何もありません。モジュラーJSパターンが好きな場合は、工場に行きます。コンストラクター関数(「クラス」)スタイルが好きな場合は、サービスにアクセスしてください。どちらのスタイルもプライベートメンバーをサポートしていることに注意してください。

このサービスの利点は、OOPの観点から見るとより直感的である可能性があります。「クラス」を作成し、プロバイダーと組み合わせて、モジュール間で同じコードを再利用し、インスタンス化されたオブジェクトの動作を、構成ブロックのコンストラクターに対するさまざまなパラメーター。


configブロックのコンストラクターにさまざまなパラメーターを提供することによって、あなたが何を意味するのかの例を提供できますか?単なるサービスまたはファクトリーの場合、パラメーターをどのように提供しますか。「プロバイダーとの連携」とはどういう意味ですか?構成できるので、私のオブジェクトの多くは、ファクトリーまたはサービスではなくプロバイダーである必要があると思います。
timbrown 2015

2

ファクトリーがサービスと比較して実行できない、または実行できることは何もありません。そしてその逆。工場はもっと人気があるようです。その理由は、プライベート/パブリックメンバーを処理する際の利便性です。この点で、サービスはより不器用になります。サービスをコーディングするとき、「this」キーワードを使用してオブジェクトメンバーを公開する傾向があり、それらのパブリックメンバーがプライベートメソッド(つまり、内部関数)から見えないことが突然わかる場合があります。

var Service = function(){

  //public
  this.age = 13;

  //private
  function getAge(){

    return this.age; //private does not see public

  }

  console.log("age: " + getAge());

};

var s = new Service(); //prints 'age: undefined'

Angularは「新しい」キーワードを使用してサービスを作成するため、Angularがコントローラーに渡すインスタンスにも同じ欠点があります。もちろん、これを使用することで問題を解決できます。

var Service = function(){

  var that = this;

  //public
  this.age = 13;

  //private
  function getAge(){

    return that.age;

  }

  console.log("age: " + getAge());

};

var s = new Service();// prints 'age: 13'  

しかし、Service定数が大きいと、これによってコードが読みにくくなります。さらに、サービスプロトタイプにはプライベートメンバーは表示されません。パブリックメンバーのみが使用できます。

var Service = function(){

  var name = "George";

};

Service.prototype.getName = function(){

  return this.name; //will not see a private member

};

var s = new Service();
console.log("name: " + s.getName());//prints 'name: undefined'

まとめると、Factoryを使用する方が便利です。工場にはこれらの欠点はありません。デフォルトで使用することをお勧めします。


この回答にはいくつかの問題があります。まず、この投稿では、AngularJSサービスがどのように機能するかではなく、字句スコープに関するJavaScriptの概念を示します。次に、呼び出しのコンテキストがmyapp.service(...)完全に失われています。どこがされたnew Service()サービス機能やサービスが注入された場所で、呼ばれるようになって。3番目のリストは、のコンテキストでは不可能ですmyapp.service ('Service', function() {...})
lanoxx 2016年

2

すべてのサービスとファクトリーがシングルトンであると彼らが言っても、私はそれに100%同意しません。工場はシングルトンではなく、これが私の答えのポイントです。すべてのコンポーネント(サービス/ファクトリー)を定義する名前について本当に考えます。つまり、

工場シングルトンではないので、あなたはそれがオブジェクトの工場のように動作しますので、あなたは、注入したときにあなたが好きな数だけ作成することができます。ドメインのエンティティのファクトリを作成し、モデルのオブジェクトのようにできるこのオブジェクトをより快適に操作できます。複数のオブジェクトを取得すると、それらをこのオブジェクトにマッピングして、DDBBとAngularJsモデルの間の別のレイヤーとして機能させることができます。オブジェクトにメソッドを追加して、AngularJsアプリをもう少しオブジェクト指向にすることができます。

一方、サービスはシングルトンであるため、作成できるのは1種類のみであり、作成できない可能性がありますが、コントローラーに注入するときにインスタンスが1つしかないため、サービスは一般的なサービスのようなものを提供します(レストコール、機能など)。コントローラに。

概念的には、サービスがサービスを提供するように考えることができ、ファクトリーはクラスの複数のインスタンス(オブジェクト)を作成できます


0

サービス

構文:module.service( 'serviceName'、function); 結果:serviceNameを注入可能な引数として宣言すると、module.serviceに渡される実際の関数参照が提供されます。

使用法:注入された関数参照に()を追加するだけで呼び出すことができるユーティリティ関数を共有するのに役立ちます。また、injectedArg.call(this)などで実行できます。

工場

構文:module.factory( 'factoryName'、function);

結果:factoryNameを注入可能な引数として宣言すると、module.factoryに渡された関数参照を呼び出すことによって返される値が提供されます。

使用法:インスタンスを作成するために新規作成できる「クラス」関数を返すのに役立ちます。

プロバイダー

構文:module.provider( 'providerName'、function);

結果:providerNameを注入可能な引数として宣言すると、module.providerに渡された関数参照の$ getメソッドを呼び出すことによって返される値が提供されます。

使用法:インスタンスを作成するために新規作成できる「クラス」関数を返すのに役立ちますが、注入する前になんらかの構成が必要です。おそらく、プロジェクト全体で再利用可能なクラスに役立つでしょうか?これについてはまだ漠然としている。


0

両方を使用することができますあなたが望む方法:かどうかのオブジェクトを作成またはJ 機能にアクセスするためにUSTを両方から


サービスから新しいオブジェクトを作成できます

app.service('carservice', function() {
    this.model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
});

.controller('carcontroller', function ($scope,carservice) { 
    $scope = new carservice.model();
})

注意 :

  • デフォルトでは、サービスはオブジェクトを返し、コンストラクタ関数は返しません。
  • そのため、コンストラクター関数がthis.modelプロパティに設定されます。
  • このサービスのためにオブジェクトが返されますが、そのオブジェクト内にはコンストラクター関数があり、新しいオブジェクトの作成に使用されます。

ファクトリから新しいオブジェクトを作成できます

app.factory('carfactory', function() {
    var model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
    return model;
});

.controller('carcontroller', function ($scope,carfactory) { 
    $scope = new carfactory();
})

注意 :

  • デフォルトでは、ファクトリはオブジェクトではなくコンストラクタ関数を返します。
  • そのため、コンストラクター関数を使用して新しいオブジェクトを作成できます。

単純な機能にアクセスするだけのサービスを作成する

app.service('carservice', function () {
   this.createCar = function () {
       console.log('createCar');
   };
   this.deleteCar = function () {
       console.log('deleteCar');
   };
});

.controller('MyService', function ($scope,carservice) { 
    carservice.createCar()
})

単純な関数にアクセスするためのファクトリを作成する

app.factory('carfactory', function () {
    var obj = {} 
        obj.createCar = function () {
            console.log('createCar');
        };
       obj.deleteCar = function () {
       console.log('deleteCar');
    };
});

.controller('MyService', function ($scope,carfactory) { 
    carfactory.createCar()
})

結論:

  • 新しいオブジェクトを作成する場合でも、単純な関数にアクセスする場合でも、どちらでも使用できます。
  • どちらを使用しても、パフォーマンスに影響はありません。
  • どちらもシングルトンオブジェクトであり、アプリごとに1つのインスタンスのみが作成されます。
  • 参照が渡されるすべてのインスタンスが1つだけであること。
  • 角度ドキュメンテーションファクトリではservice呼ばれ、service呼ばれます

0

最も一般的に使用される方法は、工場とサービスです。それらの唯一の違いは、ファクトリがJavaScriptプリミティブと関数を生成できる一方で、Serviceメソッドは継承階層を必要とするオブジェクトに対してよりよく機能することです。

プロバイダー関数はコアメソッドであり、他のすべての関数はその構文糖衣です。グローバル構成が必要な再利用可能なコードを構築する場合にのみ必要です。

サービスを作成するには、値、ファクトリ、サービス、プロバイダー、定数の5つの方法があります。この詳細については、こちらの角度のサービスをご覧ください。、こちらの記事を。この記事では、このすべての方法を実際のデモ例で説明しています。

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