Bingung tentang Layanan vs Pabrik

618

Seperti yang saya pahami, ketika di dalam pabrik saya mengembalikan objek yang akan disuntikkan ke controller. Ketika di dalam layanan saya berurusan dengan objek menggunakan thisdan tidak mengembalikan apa pun.

Saya berada di bawah asumsi bahwa layanan selalu singleton , dan bahwa objek pabrik baru akan disuntikkan di setiap pengontrol. Namun, ternyata, objek pabrik juga singleton?

Contoh kode untuk diperagakan:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

Ketika mengubah user.firstdalam ACtrlternyata user.firstdi BCtrljuga berubah, misalnya Useradalah tunggal?

Asumsi saya adalah bahwa instance baru disuntikkan ke controller dengan pabrik?

JvdBerg
sumber
4
Di samping "module.service" dan "module.factory" ada 2 cara lain untuk membuat layanan di AngularJS. Untuk info lebih lanjut, periksa melalui posting blog: " Cara membuat layanan AngularJS (singleton) dalam 4 cara berbeda "
Emil van Galen
Kemungkinan duplikat angular.service vs angular.factory
Kaushal28

Jawaban:

600

Semua layanan sudut adalah lajang :

Documents (lihat Layanan sebagai lajang ): https://docs.angularjs.org/guide/services

Terakhir, penting untuk menyadari bahwa semua layanan Angular adalah lajang aplikasi. Ini berarti bahwa hanya ada satu contoh layanan yang diberikan per injector.

Pada dasarnya perbedaan antara layanan dan pabrik adalah sebagai berikut:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Lihat presentasi ini tentang $ berikan: http://slides.wesalvaro.com/20121113/#/

Slide tersebut digunakan di salah satu pertemuan AngularJs: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html

matys84pl
sumber
13
Lihat juga stackoverflow.com/questions/15666048/... yang membahas perbedaan antara layanan, pabrik, dan penawaran.
Mark Rajcok
31
Doc resmi tidak langsung [sic! not enought clear] menyiratkan bahwa bahkan jika Anda mendefinisikan layanan dengan pabrik, itu dibuat hanya sekali. Dengan kata lain itu TIDAK dibuat lagi sesuai referensi (titik injeksi) -apapun Anda menyebutnya. Kedua cara menghasilkan instance tunggal per injektor.
honzajde
3
Anda mengatakan "layanan hanyalah fungsi konstruktor yang akan dipanggil dengan 'baru'" tapi saya pikir itu menyesatkan. Saya tidak berpikir itu disebut dengan yang baru di belakang layar, saya pikir pengembang bertanggung jawab untuk memanggilnya new.
Tim Kindberg
5
@nfiniteloop, periksa kode sumber di dekat baris 3574. Pabrik adalah metode $ get penyedia, dan layanan menghasilkan pabrik menggunakan metode yang memanggil $ injector.instantiate pada fungsi yang disediakan, yang kemudian memanggil baru. ( Lihat Docs )
citizenslave
14
Saya mendapat kesan bahwa sebuah layanan sama seperti yang Anda gunakan dengan mendapatkan referensi untuk itu. Dan sebuah pabrik adalah singleton yang mengembalikan objek baru setiap kali. Artinya, sebuah layanan akan memberi Anda satu "mobil" dan semua yang ada di proyek Anda akan menggunakan mobil ini. Sementara pabrik akan memberi Anda mobil baru setiap kali Anda memanggil pabrik. Satu adalah singleton yang mengembalikan singleton dan satu adalah singleton yang mengembalikan sebuah objek. Adakah yang bisa menjelaskan? Menyebut semuanya singleton tidak membantu karena dapat merujuk ke banyak hal.
user2483724
380

Bagi saya wahyu datang ketika saya menyadari bahwa mereka semua bekerja dengan cara yang sama: dengan menjalankan sesuatu sekali , menyimpan nilai yang mereka dapatkan, dan kemudian batuk nilai tersimpan yang sama ketika dirujuk melalui Dependency Injection.

Katakanlah kita memiliki:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

Perbedaan antara ketiganya adalah:

  1. aNilai yang disimpan berasal dari menjalankan fn, dengan kata lain:fn()
  2. bNilai yang disimpan berasal dari newing fn, dengan kata lain:new fn()
  3. cNilai yang disimpan berasal dari pertama mendapatkan instance dengan newing fn, dan kemudian menjalankan $getmetode instance

yang berarti, ada sesuatu seperti objek cache di dalam angular, yang nilainya setiap injeksi hanya diberikan satu kali, ketika mereka telah disuntikkan pertama kali, dan di mana:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

Inilah sebabnya kami menggunakan thisdalam layanan, dan mendefinisikan this.$getpenyedia dalam.

Semoga ini membantu.

Lucia
sumber
54
Akhirnya, penjelasan yang masuk akal. Angular itu gila dan sangat buruk hingga menyakitkan.
osiris
8
Ini harus menjadi jawaban yang diterima karena sebenarnya menjawab pertanyaan MENGAPA pabrik, layanan, dan penyedia mengembalikan nilai singleton. Jawaban lain menjelaskan perbedaan antara pabrik, layanan, dan penyedia tetapi tidak pernah menyentuh aspek tunggal.
wmock
3
Saya suka ini ... Ketika saya membaca ribuan kalimat dari blogger lain .. Saya hanya bisa mengerti pabrik. Tetapi saya membaca ini ... saya mengerti semua 3.
tsohtan
@osiris saya setuju. Saya tidak suka itu. Rasanya sangat serasi digabungkan sehingga membuat gigiku menggiling.
Thomas
2
jadi Anda harus memberikan implementasi $ get ketika menggunakan penyedia?
Victor
95

contoh hidup

Contoh "halo dunia"

dengan factory/ service/ provider:

var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});

//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});


function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {

    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}​
EpokK
sumber
57

Ada juga cara untuk mengembalikan fungsi konstruktor sehingga Anda dapat kembali newable kelas di pabrik-pabrik, seperti ini:

function MyObjectWithParam($rootScope, name) {
  this.$rootScope = $rootScope;
  this.name = name;
}
MyObjectWithParam.prototype.getText = function () {
  return this.name;
};

App.factory('MyObjectWithParam', function ($injector) {
  return function(name) { 
    return $injector.instantiate(MyObjectWithParam,{ name: name });
  };
}); 

Jadi Anda bisa melakukan ini di controller, yang menggunakan MyObjectWithParam:

var obj = new MyObjectWithParam("hello"),

Lihat di sini contoh lengkapnya:
http://plnkr.co/edit/GKnhIN?p=preview

Dan di sini halaman grup Google, di mana dibahas:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

JustGoscha
sumber
Saya mengalami masalah dengan minifikasi menggunakan contoh Anda. Apakah Anda tahu bagaimana saya harus membubuhi keterangan ini?
Pål
2
Ya, ada notasi yang diperkecil untuk Angular. Seharusnya seperti ini: App.factory('MyObjectWithParam', ['$injector', function ($injector) { return function(name) { return $injector.instantiate(MyObjectWithParam,{ name: name }); }; }]); Baca lebih lanjut di sini: docs.angularjs.org/tutorial/step_05
JustGoscha
4
mengapa Anda ingin melakukan ini, jika Anda bisa menggunakannya .service?
flup
Saya memiliki pemikiran yang sama @ flup. @ justgoscha, apakah ada manfaat ( persepsi? ) menggunakan yang .factorybertentangan .service?
xandercode
5
Saya pikir karena layanan adalah layanan tunggal . Apa yang saya bangun di sini pada dasarnya adalah sebuah kelas yang dapat digunakan. Jadi Anda dapat memiliki sesuatu seperti pabrik layanan Mobil dan kemudian membuat new Car('BMW')dan new Car('Ford')dan mereka tidak berbagi variabel dan segalanya yang sama.
JustGoscha
51

Inilah perbedaan utamanya:

Jasa

Sintaksis: module.service( 'serviceName', function );

Hasil: Saat mendeklarasikan serviceName sebagai argumen yang dapat disuntikkan, Anda akan diberikan instance fungsi yang diteruskan ke module.service.

Penggunaan: Dapat bermanfaat untuk berbagi fungsi utilitas yang berguna untuk dipanggil hanya dengan menambahkan () ke referensi fungsi yang disuntikkan. Bisa juga dijalankan dengan injectedArg.call( this )atau serupa.

Pabrik

Sintaksis: module.factory( 'factoryName', function );

Hasil: Saat mendeklarasikan factoryName sebagai argumen injeksi, Anda akan diberikan nilai yang dikembalikan dengan memohon referensi fungsi yang diteruskan ke module.factory.

Penggunaan: Dapat berguna untuk mengembalikan fungsi 'kelas' yang kemudian dapat digunakan untuk membuat instance.

Juga periksa dokumentasi AngularJS dan pertanyaan serupa tentang stackoverflow bingung tentang layanan vs pabrik .

Berikut ini adalah contoh menggunakan layanan dan pabrik . Baca lebih lanjut tentang layanan AngularJS vs pabrik .

Manish Chhabra
sumber
6
Ini masuk akal bagi saya. Pabrik ia mengembalikan cetak biru untuk membuat objek baru.
27

Menambah jawaban pertama, saya pikir .service () adalah untuk orang-orang yang telah menulis kode mereka dalam gaya yang lebih berorientasi objek (C # / Java) (menggunakan kata kunci ini dan objek instantiating melalui fungsi prototipe / Konstruktor).

Factory adalah untuk pengembang yang menulis kode yang lebih alami untuk javascript / gaya fungsional pengkodean.

Lihatlah kode sumber metode .service dan .factory di dalam angular.js - secara internal mereka semua memanggil metode penyedia:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { \
    return provider(name, { $get: factoryFn }); 
  }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }
Anand
sumber
25

Sangat sederhana:

.service - fungsi terdaftar akan dipanggil sebagai konstruktor (alias 'baru')

.factory - fungsi terdaftar akan dipanggil sebagai fungsi sederhana

Keduanya dipanggil sekali sehingga menghasilkan objek tunggal yang akan disuntikkan ke komponen lain dari aplikasi Anda.

Bingles
sumber
6
Iya. jangan membuat hal-hal lebih rumit dari yang sebenarnya
gagal
20

Semua penyedia bekerja dengan cara yang sama. Metode yang berbeda service, factory, providerhanya membiarkan Anda mencapai hal yang sama dalam kode kurang.

PS Ada juga valuedan constant.

Setiap kasus khusus di rantai mulai dengan providerdan berakhir dengan valuememiliki batasan tambahan. Jadi untuk memutuskan di antara mereka, Anda harus bertanya pada diri sendiri yang mana Anda dapat mencapai apa yang Anda inginkan dengan kode lebih sedikit.

Ini adalah gambar yang menunjukkan apa yang saya maksud:

masukkan deskripsi gambar di sini

Anda dapat rincian dan referensi panduan di posting blog saya mendapatkan gambar ini dari:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

Luis Perez
sumber
Layanan dikatakan singleton, tetapi mengapa singleton, jika instance baru sedang dibuat setiap kali saya menyuntikkannya?
Ankur Marwaha
1
@AnkurMarwaha Sebuah instance baru tidak dibuat setiap kali, itu hanya dibuat sekali dan di-cache oleh AngularJS. Ini benar apakah Anda menggunakan penyedia, pabrik, layanan, dll. Anda dapat mengonfirmasi ini menggunakan console.log()dan menyuntikkan ke beberapa pengendali.
Luis Perez
Luis, komentar Anda bertentangan dengan jawaban yang diterima seperti yang dikatakan - Terakhir, penting untuk menyadari bahwa semua layanan Angular adalah lajang aplikasi. Ini berarti bahwa hanya ada satu contoh layanan yang diberikan per injector.
Ankur Marwaha
@AnkurMarwaha mungkin saya salah paham sesuatu. Anda mengutip "penting untuk menyadari bahwa semua layanan Angular adalah lajang aplikasi" - fakta bahwa mereka lajang berarti mereka hanya dibuat sekali. Itulah yang saya katakan "Contoh baru tidak dibuat setiap kali, itu hanya dibuat sekali dan di-cache ...". Bisakah Anda menunjukkan secara lebih rinci di mana Anda melihat konflik?
Luis Perez
1
Ah, saya melihat kebingungan. "Injektor" adalah objek bersudut. Ini bertugas melakukan "injeksi". Contoh, ketika controller pertama kali dijalankan, "injector" melihat parameter dan menyuntikkan masing-masing. Hanya ada satu "injektor" untuk seluruh aplikasi Anda. Setelah injektor menciptakan pabrik atau layanan tertentu, itu membuat contoh dan menggunakannya kembali - maka singleton. Jadi hanya ada satu injector per aplikasi dan hanya satu instance dari layanan yang diberikan per injector. Sebagian besar aplikasi Angular hanya memiliki satu aplikasi, oleh karena itu satu injektor, oleh karena itu satu instance dari layanan, pengontrol, dll.
Luis Perez
13

Berikut adalah beberapa contoh layanan vs pabrik yang mungkin berguna dalam melihat perbedaan di antara mereka. Pada dasarnya, sebuah layanan memiliki "baru ..." yang dipanggil, itu sudah dipakai. Sebuah pabrik tidak secara instantiated secara otomatis.

Contoh dasar

Mengembalikan objek kelas yang memiliki metode tunggal

Berikut adalah layanan yang memiliki satu metode:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Berikut adalah pabrik yang mengembalikan objek dengan metode:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Kembalikan nilai

Pabrik yang mengembalikan daftar angka:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Layanan yang mengembalikan daftar angka:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

Output dalam kedua kasus adalah sama, daftar angka.

Contoh lanjutan

Variabel "Kelas" menggunakan pabrik

Dalam contoh ini kita mendefinisikan CounterFactory, itu menambah atau mengurangi counter dan Anda bisa mendapatkan jumlah saat ini atau mendapatkan berapa banyak objek CounterFactory telah dibuat:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

Kami menggunakan CounterFactoryuntuk membuat banyak penghitung. Kita dapat mengakses variabel kelas untuk melihat berapa banyak penghitung yang dibuat:

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

Output dari kode ini adalah:

people 0
people 1
counters 1
places 0
counters 2
counters 2

sumber
itu contoh yang berguna, number_of_counter_factories seperti meta atrribute dari kelas CounterFactory, kan ?, saya mengerti contoh ini dapat ditiru pada layanan (beri tahu saya jika saya salah), apa perbedaan semantik dalam kasus ini?
geoom
Contoh yang berguna! Jadi ini pada dasarnya berarti bahwa di sebuah pabrik Anda dapat memiliki lapisan abstraksi ekstra yang tidak akan diperoleh dalam layanan. Apapun yang dikembalikan, contoh baru akan dikembalikan kapan pun 'baru' digunakan. Setiap variabel yang tidak dideklarasikan di dalam blok kembali akan menjadi tunggal. Apakah saya benar?
Swanidhi
@Swanidhi pada dasarnya ya, Anda dapat mendeklarasikan variabel yang lajang di pabrik. Itu sebabnya saya menyebutnya variabel "kelas".
13

"Pabrik" dan "Layanan" adalah berbagai cara melakukan DI (Dependency injection) dalam sudut.

Jadi ketika kita mendefinisikan DI menggunakan "layanan" seperti yang ditunjukkan pada kode di bawah ini. Ini menciptakan instance GLOBAL baru dari objek "Logger" dan menyuntikkannya ke fungsi.

app.service("Logger", Logger); // Injects a global object

Ketika Anda mendefinisikan DI menggunakan "pabrik" itu tidak membuat instance. Itu hanya melewati metode dan kemudian konsumen secara internal harus membuat panggilan ke pabrik untuk contoh objek.

app.factory("Customerfactory", CreateCustomer);

Di bawah ini adalah gambar sederhana yang menunjukkan secara visual bagaimana proses DI untuk "Layanan" berbeda dari "Pabrik".

masukkan deskripsi gambar di sini

Pabrik harus digunakan Ketika kita ingin membuat berbagai jenis objek tergantung pada skenario. Misalnya tergantung pada skenario kami ingin membuat objek "Pelanggan" sederhana, atau "Pelanggan" dengan objek "Alamat" atau "Pelanggan" dengan objek "Telepon". Berikut ini penjelasan terperinci dari paragraf ini

Layanan harus digunakan Ketika kita memiliki utilitas atau fungsi bersama yang akan disuntikkan seperti Utilitas, Logger, Penangan kesalahan dll.

Shivprasad Koirala
sumber
Setiap jawaban yang saya lihat pada pertanyaan ini dan yang serupa lainnya menentukan perbedaan dalam mekanika dan sintaksis. Jawaban ini memberikan alasan nyata mengapa Anda memilih satu di atas yang lain. Ini masalah semantik dan melihat nama, layanan atau pabrik, mengomunikasikan tujuan mereka dan bagaimana mereka digunakan.
Joe Mayo
8

Gaya layanan : ( mungkin yang paling sederhana ) mengembalikan fungsi sebenarnya: Berguna untuk berbagi fungsi utilitas yang berguna untuk dipanggil hanya dengan menambahkan () ke referensi fungsi yang disuntikkan.

Layanan di AngularJS adalah objek JavaScript tunggal yang berisi serangkaian fungsi

var myModule = angular.module("myModule", []);

myModule.value  ("myValue"  , "12345");

function MyService(myValue) {
    this.doIt = function() {
        console.log("done: " + myValue;
    }
}

myModule.service("myService", MyService);
myModule.controller("MyController", function($scope, myService) {

    myService.doIt();

});

Gaya pabrik : ( lebih terlibat tetapi lebih canggih ) mengembalikan nilai pengembalian fungsi: instantiate objek seperti Object baru () di java.

Pabrik adalah fungsi yang menciptakan nilai. Ketika suatu layanan, pengontrol, dll. Membutuhkan suatu nilai yang disuntikkan dari suatu pabrik, pabrik tersebut menciptakan nilai berdasarkan permintaan. Setelah dibuat, nilai tersebut digunakan kembali untuk semua layanan, pengontrol, dll. Yang perlu disuntikkan.

var myModule = angular.module("myModule", []);

myModule.value("numberValue", 999);

myModule.factory("myFactory", function(numberValue) {
    return "a value: " + numberValue;
})  
myModule.controller("MyController", function($scope, myFactory) {

    console.log(myFactory);

});

Gaya penyedia : ( versi penuh, dapat dikonfigurasi ) mengembalikan output dari fungsi $ get fungsi: Dapat dikonfigurasi.

Penyedia di AngularJS adalah bentuk pabrik paling fleksibel yang dapat Anda buat. Anda mendaftarkan penyedia dengan modul seperti yang Anda lakukan dengan layanan atau pabrik, kecuali Anda menggunakan fungsi provider ().

var myModule = angular.module("myModule", []);

myModule.provider("mySecondService", function() {
    var provider = {};
    var config   = { configParam : "default" };

    provider.doConfig = function(configParam) {
        config.configParam = configParam;
    }

    provider.$get = function() {
        var service = {};

        service.doService = function() {
            console.log("mySecondService: " + config.configParam);
        }

        return service;
    }

    return provider;
});

myModule.config( function( mySecondServiceProvider ) {
    mySecondServiceProvider.doConfig("new config param");
});

myModule.controller("MyController", function($scope, mySecondService) {

    $scope.whenButtonClicked = function() {
        mySecondService.doIt();
    }

});

src jenkov

<!DOCTYPE html>
    <html ng-app="app">
    <head>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    	<meta charset=utf-8 />
    	<title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
    	{{serviceOutput}}
    	<br/><br/>
    	{{factoryOutput}}
    	<br/><br/>
    	{{providerOutput}}
    
    	<script>
    
    		var app = angular.module( 'app', [] );
    
    		var MyFunc = function() {
    
    			this.name = "default name";
    
    			this.$get = function() {
    				this.name = "new name"
    				return "Hello from MyFunc.$get(). this.name = " + this.name;
    			};
    
    			return "Hello from MyFunc(). this.name = " + this.name;
    		};
    
    		// returns the actual function
    		app.service( 'myService', MyFunc );
    
    		// returns the function's return value
    		app.factory( 'myFactory', MyFunc );
    
    		// returns the output of the function's $get function
    		app.provider( 'myProv', MyFunc );
    
    		function MyCtrl( $scope, myService, myFactory, myProv ) {
    
    			$scope.serviceOutput = "myService = " + myService;
    			$scope.factoryOutput = "myFactory = " + myFactory;
    			$scope.providerOutput = "myProvider = " + myProv;
    
    		}
    
    	</script>
    
    </body>
    </html>

jsbin

<!DOCTYPE html>
<html ng-app="myApp">
<head>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
	<meta charset=utf-8 />
	<title>JS Bin</title>
</head>
<body>
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
	<script>

	var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});
    
//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});
        

function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}
	</script>

</body>
</html>

jsfiddle

Premraj
sumber
2

Perbedaan mendasar, adalah bahwa penyedia memungkinkan untuk menetapkan nilai-nilai fungsi primitif (non-objek), array, atau panggilan balik ke dalam variabel yang dinyatakan pabrik, dan dengan demikian jika mengembalikan objek itu harus dinyatakan dan dikembalikan secara eksplisit.

Di sisi lain, layanan hanya dapat digunakan untuk mengatur variabel yang dinyatakan layanan ke objek, sehingga kami dapat menghindari pembuatan eksplisit dan pengembalian objek, sementara di sisi lain ia memungkinkan penggunaan kata kunci ini .

Atau dengan kata singkat " penyedia adalah bentuk yang lebih umum sementara layanan terbatas pada objek saja".

halo yoel
sumber
2

Inilah bagaimana saya memahami perbedaan di antara mereka dalam hal pola desain:

Layanan : Mengembalikan suatu jenis, yang akan diberitakan baru untuk membuat objek jenis itu. Jika analogi Java digunakan, Layanan mengembalikan definisi Kelas Java .

Pabrik : Mengembalikan benda konkret yang dapat segera digunakan. Dalam Java Analogy, Factory mengembalikan Object Java .

Bagian yang sering membingungkan orang (termasuk saya) adalah bahwa ketika Anda menyuntikkan Layanan atau Pabrik dalam kode Anda, mereka dapat digunakan dengan cara yang sama, apa yang Anda dapatkan dalam kode Anda dalam kedua kasus adalah objek konkret yang dapat segera Anda panggil. Yang berarti dalam hal Layanan, panggilan sudut "baru" pada deklarasi layanan atas nama Anda. Saya pikir ini adalah konsep yang berbelit-belit.

Hisyam
sumber
1

Ini akan menjadi jawaban terbaik dan singkat untuk memahami Service Vs Factory Vs Provider

Sumber : https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J

Inilah yang dikatakan ben dengan demo http://jsbin.com/ohamub/1/edit?html,output

"Ada komentar dalam kode yang mengilustrasikan perbedaan utama tetapi saya akan sedikit memperluasnya di sini. Sebagai catatan, saya hanya memikirkan hal ini jadi jika saya mengatakan sesuatu yang salah, tolong beri tahu saya.

Jasa

Sintaks : module.service ('serviceName', function);

Hasil : Saat mendeklarasikan serviceName sebagai argumen injeksi, Anda akan diberikan referensi fungsi aktual yang diteruskan ke module.service.

Penggunaan : Dapat bermanfaat untuk berbagi fungsi utilitas yang berguna untuk dipanggil hanya dengan menambahkan () ke referensi fungsi yang disuntikkan. Bisa juga dijalankan dengan injectedArg.call (ini) atau yang serupa.

Pabrik

Sintaks : module.factory ('factoryName', fungsi);

Hasil : Saat mendeklarasikan factoryName sebagai argumen injeksi, Anda akan diberikan nilai yang dikembalikan dengan memohon referensi fungsi yang diteruskan ke module.factory.

Penggunaan : Dapat berguna untuk mengembalikan fungsi 'kelas' yang kemudian dapat digunakan untuk membuat instance.

Penyedia

Sintaks : module.provider ('providerName', function);

Hasil : Ketika mendeklarasikan providerName sebagai argumen injeksi, Anda akan diberikan nilai yang dikembalikan dengan memanggil metode $ get dari referensi fungsi yang diteruskan ke module.provider.

Penggunaan : Dapat berguna untuk mengembalikan fungsi 'kelas' yang kemudian dapat baru untuk membuat instance tetapi yang membutuhkan semacam konfigurasi sebelum disuntikkan. Mungkin berguna untuk kelas yang dapat digunakan kembali di seluruh proyek? Masih agak kabur untuk yang satu ini. "Ben

Syed Ekram Uddin
sumber
1

Saya memiliki kebingungan ini untuk sementara waktu dan saya mencoba yang terbaik untuk memberikan penjelasan sederhana di sini. Semoga ini bisa membantu!

angular .factorydan angular .servicekeduanya digunakan untuk menginisialisasi layanan dan bekerja dengan cara yang sama.

Satu-satunya perbedaan adalah, bagaimana Anda ingin menginisialisasi layanan Anda.

Keduanya lajang


var app = angular.module('app', []);


Pabrik

app.factory ( <service name>, <function with a return value>)

Jika Anda ingin menginisialisasi layanan Anda dari fungsi yang Anda miliki dengan nilai kembali , Anda harus menggunakan factorymetode ini .

misalnya

function myService() {
  //return what you want
  var service = {
    myfunc: function (param) { /* do stuff */ }
  }
  return service;
}

app.factory('myService', myService);

Saat menyuntikkan layanan ini (misalnya ke controller Anda):

  • Angular akan memanggil fungsi yang Anda berikan (sebagai myService()) untuk mengembalikan objek
  • Singleton - dipanggil hanya sekali, disimpan, dan lulus objek yang sama.


Layanan

app.service ( <service name>, <constructor function>)

Jika Anda ingin menginisialisasi layanan Anda dari fungsi konstruktor (menggunakan thiskata kunci), Anda harus menggunakan servicemetode ini .

misalnya

function myService() {
  this.myfunc: function (param) { /* do stuff */ }
}

app.service('myService', myService);

Saat menyuntikkan layanan ini (misalnya ke controller Anda):

  • Angular akan memasukkan newfungsi yang Anda berikan (as new myService()) untuk mengembalikan objek
  • Singleton - dipanggil hanya sekali, disimpan, dan lulus objek yang sama.


CATATAN: Jika Anda menggunakan factorydengan <constructor function>atau servicedengan <function with a return value>, itu tidak akan berfungsi.


Contoh - DEMO

Safeuss Hussain
sumber
1

Inilah yang membantu saya memahami perbedaannya, berkat posting blog oleh Pascal Precht.

Layanan adalah metode pada modul yang mengambil nama dan fungsi yang mendefinisikan layanan. Anda dapat menyuntikkan dan menggunakan layanan khusus itu di komponen lain, seperti pengontrol, arahan dan filter. Pabrik adalah metode pada modul dan juga membutuhkan nama dan fungsi, yang mendefinisikan pabrik. Kami juga dapat menyuntikkan dan menggunakannya dengan cara yang sama kami lakukan dengan layanan.

Objek yang dibuat dengan menggunakan nilai properti prototipe dari fungsi konstruktor mereka sebagai prototipe mereka, jadi saya menemukan kode Angular yang memanggil Object.create (), yang saya percaya adalah fungsi konstruktor layanan ketika akan dipakai. Namun, fungsi pabrik sebenarnya hanya fungsi yang dipanggil, itulah sebabnya kita harus mengembalikan objek literal untuk pabrik.

Berikut adalah kode sudut 1,5 yang saya temukan untuk pabrik:

var needsRecurse = false;
    var destination = copyType(source);

    if (destination === undefined) {
      destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
      needsRecurse = true;
    }

Cuplikan kode sumber sudut untuk fungsi factory ():

 function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
  }

Dibutuhkan nama dan fungsi pabrik yang dilewati dan mengembalikan penyedia dengan nama yang sama, yang memiliki metode $ get yang merupakan fungsi pabrik kami. Setiap kali Anda meminta injector untuk ketergantungan tertentu, ia pada dasarnya meminta penyedia terkait untuk sebuah instance dari layanan itu, dengan memanggil metode $ get (). Karena itulah diperlukan $ get () saat membuat penyedia.

Berikut adalah kode 1,5 sudut untuk layanan.

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

Ternyata ketika kita memanggil service (), sebenarnya memanggil factory ()! Namun, tidak hanya meneruskan fungsi konstruktor layanan kami ke pabrik apa adanya. Itu juga melewati fungsi yang meminta injektor untuk instantiate objek oleh konstruktor yang diberikan.

Dengan kata lain, jika kita menyuntikkan MyService di suatu tempat, yang terjadi dalam kode adalah:

MyServiceProvider.$get(); // return the instance of the service

Untuk menyatakannya kembali, sebuah layanan memanggil sebuah pabrik, yang merupakan metode $ get () pada penyedia terkait. Selain itu, $ injector.instantiate () adalah metode yang akhirnya memanggil Object.create () dengan fungsi konstruktor. Itu sebabnya kami menggunakan "ini" dalam layanan.

Untuk ES5 tidak masalah yang kami gunakan: service () atau factory (), itu selalu merupakan pabrik yang disebut yang menciptakan penyedia untuk layanan kami.

Anda dapat melakukan hal yang sama persis dengan layanan juga. Layanan adalah fungsi konstruktor, namun, itu tidak mencegah kita mengembalikan objek literal. Jadi kita dapat mengambil kode layanan kami dan menuliskannya dengan cara yang pada dasarnya melakukan hal yang sama persis seperti pabrik kami atau dengan kata lain, Anda dapat menulis layanan sebagai pabrik untuk mengembalikan objek.

Mengapa kebanyakan orang merekomendasikan untuk menggunakan pabrik di atas layanan? Ini adalah jawaban terbaik yang pernah saya lihat yang berasal dari buku Pawel Kozlowski: Menguasai Pengembangan Aplikasi Web dengan AngularJS.

Metode pabrik adalah cara paling umum untuk memasukkan objek ke sistem injeksi ketergantungan AngularJS. Ini sangat fleksibel dan dapat berisi logika kreasi yang canggih. Karena pabrik adalah fungsi reguler, kita juga dapat memanfaatkan ruang lingkup leksikal baru untuk mensimulasikan variabel "pribadi". Ini sangat berguna karena kami dapat menyembunyikan detail implementasi layanan yang diberikan. "

James Drinkard
sumber
1
  • Dengan pabrik Anda benar-benar membuat objek di dalam pabrik dan mengembalikannya.
  • Dengan layanan ini Anda hanya memiliki fungsi standar yang menggunakan thiskata kunci untuk mendefinisikan fungsi.
  • Dengan penyedia ada $getAnda mendefinisikan dan dapat digunakan untuk mendapatkan objek yang mengembalikan data.
Oskar
sumber
1

Ada tiga cara menangani logika bisnis di AngularJS: ( Terinspirasi oleh kursus Coursera AngularJS Yaakov ) yaitu:

  1. Layanan
  2. Pabrik
  3. Pemberi

Di sini kita hanya akan berbicara tentang Service vs Factory

LAYANAN :

Sintaksis:

app.js

 var app = angular.module('ServiceExample',[]);
 var serviceExampleController =
              app.controller('ServiceExampleController', ServiceExampleController);
 var serviceExample = app.service('NameOfTheService', NameOfTheService);

 ServiceExampleController.$inject = ['NameOfTheService'] //very important as this protects from minification of js files

function ServiceExampleController(NameOfTheService){
     serviceExampleController = this;
     serviceExampleController.data = NameOfTheService.getSomeData();
 }

function NameOfTheService(){
     nameOfTheService = this;
     nameOfTheService.data = "Some Data";
     nameOfTheService.getSomeData = function(){
           return nameOfTheService.data;
     }     
}

index.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

Fitur utama Layanan:

  1. Lazily Instantiated : Jika layanan ini tidak disuntikkan, itu tidak akan pernah instantiated. Jadi untuk menggunakannya Anda harus menyuntikkannya ke modul.

  2. Singleton : Jika disuntikkan ke beberapa modul, semua akan memiliki akses hanya ke satu instance tertentu. Itu sebabnya, sangat nyaman untuk berbagi data di seluruh pengontrol yang berbeda.

PABRIK

Sekarang mari kita bicara tentang Factory in AngularJS

Pertama mari kita lihat sintaks :

app.js :

var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);

//first implementation where it returns a function
function NameOfTheFactoryOne(){
   var factory = function(){
      return new SomeService();
    }
   return factory;
}

//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
   var factory = {
      getSomeService : function(){
          return new SomeService();
       }
    };
   return factory;
}

Sekarang menggunakan dua di atas di controller:

 var factoryOne = NameOfTheFactoryOne() //since it returns a function
 factoryOne.someMethod();

 var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
 factoryTwo.someMethod();

Fitur pabrik:

  1. Jenis layanan ini mengikuti pola desain pabrik . Pabrik dapat dianggap sebagai tempat sentral yang menciptakan objek atau metode baru.

  2. Ini tidak hanya menghasilkan singleton, tetapi juga layanan yang dapat disesuaikan.

  3. The .service()Metode adalah pabrik yang selalu menghasilkan jenis yang sama dari layanan, yang merupakan tunggal. Tidak ada cara mudah untuk mengkonfigurasi perilaku itu. Itu .service()metode biasanya digunakan sebagai jalan pintas untuk sesuatu yang tidak memerlukan apapun konfigurasi.

Pritam Banerjee
sumber
0

Anda dapat memahami perbedaannya dengan analogi ini - Pertimbangkan perbedaan antara fungsi normal yang akan mengembalikan beberapa nilai dan fungsi konstruktor yang akan dipakai di awal menggunakan kata kunci baru. sebuah objek) sedangkan menciptakan layanan seperti menciptakan fungsi konstruktor (kelas OO) yang kita dapat membuat contoh menggunakan kata kunci baru. Satu-satunya hal yang perlu diperhatikan adalah di sini adalah bahwa ketika kita menggunakan metode Layanan untuk membuat layanan, itu akan secara otomatis membuat contohnya menggunakan mekanisme injeksi ketergantungan yang didukung oleh AngularJS

Sourabh Ranka
sumber