AngularJS: Kapan menggunakan layanan alih-alih pabrik


296

Tolong bersamaku di sini. Saya tahu ada jawaban lain seperti: AngularJS: Layanan vs penyedia vs pabrik

Namun saya masih tidak tahu kapan Anda akan menggunakan layanan di pabrik.

Dari apa yang saya tahu pabrik biasanya digunakan untuk membuat fungsi "umum" yang dapat dipanggil oleh beberapa Pengontrol: Membuat fungsi pengendali umum

Dokumen Angular tampaknya lebih memilih pabrik daripada layanan. Mereka bahkan merujuk ke "layanan" ketika mereka menggunakan pabrik yang bahkan lebih membingungkan! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Jadi kapan seseorang akan menggunakan layanan?

Adakah sesuatu yang hanya mungkin atau lebih mudah dilakukan dengan layanan?

Adakah hal berbeda yang terjadi di balik layar? Perbedaan kinerja / memori?

Ini sebuah contoh. Selain metode deklarasi, mereka tampak identik dan saya tidak tahu mengapa saya melakukan yang satu vs yang lain. http://jsfiddle.net/uEpkE/

Pembaruan: Dari jawaban Thomas, sepertinya menyiratkan bahwa layanan adalah untuk logika yang lebih sederhana dan pabrik untuk logika yang lebih kompleks dengan metode pribadi, jadi saya memperbarui kode biola di bawah ini dan tampaknya keduanya dapat mendukung fungsi pribadi?

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()
    ];
}

tentu saja layanan mendukung pribadi tetapi jika Anda membaca posting saya dengan benar itu murni gaya kode: kami juga dapat memanfaatkan ruang lingkup leksikal baru untuk mensimulasikan variabel "pribadi". Itu "SIMULAT"
Thomas Pons

Saya menemukan diskusi ini sangat berguna stackoverflow.com/questions/15666048/...
Anand Gupta

Jawaban:


280

Penjelasan

Anda punya berbagai hal di sini:

Pertama:

  • Jika Anda menggunakan layanan, Anda akan mendapatkan contoh fungsi ( this"kata kunci).
  • Jika Anda menggunakan pabrik, Anda akan mendapatkan nilai yang dikembalikan dengan menggunakan referensi fungsi (pernyataan pengembalian di pabrik).

ref: angular.service vs angular.factory

Kedua:

Ingatlah semua penyedia di AngularJS (nilai, konstan, layanan, pabrik) adalah lajang!

Ketiga:

Menggunakan satu atau yang lain (layanan atau pabrik) adalah tentang gaya kode. Tapi, cara umum di AngularJS adalah menggunakan pabrik .

Mengapa

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

( ref : http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821 ).


Pemakaian

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

Factory: Dapat bermanfaat untuk mengembalikan fungsi 'kelas' yang kemudian dapat baru untuk membuat instance.

Jadi, gunakan pabrik ketika Anda memiliki logika kompleks dalam layanan Anda dan Anda tidak ingin mengekspos kompleksitas ini .

Dalam kasus lain, jika Anda ingin mengembalikan instance layanan, gunakan saja layanan .

Tapi Anda akan melihat dengan waktu bahwa Anda akan menggunakan pabrik dalam 80% kasus saya pikir.

Untuk lebih jelasnya: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


PEMBARUAN:

Pos yang sangat baik di sini: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

"Jika kamu ingin fungsi kamu dipanggil seperti fungsi normal , gunakan pabrik . Jika kamu ingin fungsi kamu dipakai instantiated dengan operator baru, gunakan layanan. Jika kamu tidak tahu bedanya, gunakan pabrik."


PEMBARUAN:

Tim AngularJS melakukan pekerjaannya dan memberikan penjelasan: http://docs.angularjs.org/guide/providers

Dan dari halaman ini:

"Pabrik dan Layanan adalah resep yang paling umum digunakan. Satu-satunya perbedaan di antara mereka adalah bahwa resep Layanan berfungsi lebih baik untuk objek jenis kustom, sedangkan Pabrik dapat menghasilkan primitif dan fungsi JavaScript."


7
Re Pertama: Saya membacanya di mana-mana tetapi saya tidak mengerti implikasi praktisnya. Saya kira dari jawaban Anda tidak ada perbedaan praktis "sebagian besar"? Terima kasih atas referensi buku ini!
user1941747

Sangat sederhana jika layanan Anda benar-benar kompleks dan Anda memerlukan metode dan objek pribadi menggunakan pabrik
Thomas Pons

1
Saya perhatikan Anda menambahkan "Jika Anda ingin mengembalikan turunan sebuah layanan, gunakan saja layanan". Pertanyaan tindak lanjut saya adalah KAPAN Anda ingin mengembalikan contoh layanan? Saya mencoba menemukan kasus penggunaan khusus di sini.
user1941747

12
"Karena pabrik adalah fungsi reguler, kita juga dapat memanfaatkan ruang lingkup leksikal baru untuk mensimulasikan variabel" pribadi "." - ini tidak khusus untuk pabrik, Anda dapat melakukan hal yang sama dengan layanan ..
pootzko

Tampaknya tim Google lebih memilih layanan daripada pabrik, ini membuat segalanya lebih membingungkan! google-styleguide.googlecode.com/svn/trunk/…
xzhang

111

allernhwkim awalnya mengirim jawaban pada pertanyaan ini yang menghubungkan ke blognya , namun seorang moderator menghapusnya. Ini satu-satunya pos yang saya temukan yang tidak hanya memberi tahu Anda bagaimana melakukan hal yang sama dengan layanan, penyedia dan pabrik, tetapi juga memberi tahu Anda apa yang dapat Anda lakukan dengan penyedia yang tidak dapat Anda lakukan dengan pabrik, dan dengan sebuah pabrik yang Anda tidak bisa dengan layanan.

Langsung dari blognya:

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;
    }      
});

Ini menunjukkan bagaimana CarService akan selalu menghasilkan mobil dengan 4 silinder, Anda tidak dapat mengubahnya untuk setiap mobil. Sedangkan CarFactory mengembalikan fungsi sehingga Anda dapat melakukannya new CarFactorydi controller Anda, melewati sejumlah silinder khusus untuk mobil itu. Anda tidak dapat melakukannya new CarServicekarena CarService adalah objek bukan fungsi.

Alasan pabrik tidak bekerja seperti ini:

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

Dan secara otomatis mengembalikan fungsi bagi Anda untuk instantiate, karena Anda tidak dapat melakukan ini (tambahkan hal-hal ke prototipe / etc):

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

Lihat bagaimana sebenarnya pabrik yang memproduksi mobil.

Kesimpulan dari blognya cukup bagus:

Kesimpulannya,

---------------------------------------------------  
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------  
| Factory | Yes      | Yes          | No          |
---------------------------------------------------  
| Service | Yes      | No           | No          |
---------------------------------------------------  
| Provider| Yes      | Yes          | Yes         |       
---------------------------------------------------  
  1. Gunakan Layanan saat Anda hanya membutuhkan objek sederhana seperti Hash, misalnya {foo; 1, bar: 2} Mudah untuk dikodekan, tetapi Anda tidak dapat membuat instantiate.

  2. Gunakan Pabrik saat Anda perlu membuat instance objek, yaitu Pelanggan baru (), Komentar baru (), dll.

  3. Gunakan Penyedia saat Anda perlu mengkonfigurasinya. yaitu url uji, url QA, url produksi.

Jika Anda baru saja mengembalikan objek di pabrik, Anda mungkin harus menggunakan layanan.

Jangan lakukan ini:

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

Gunakan layanan sebagai gantinya:

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

11
ini sangat membantu saya. +1 untuk tabel perbandingan
Vu Anh

5
jika Anda mendefinisikan fungsi layanan dengan satu parameter numCylinder maka ia akan memiliki fleksibilitas yang sama dengan metode pabrik
Ovi

pergi dan baca posting blog, dan buang-buang waktu Anda mencoba mencari sudut, jika Anda tahu javascript setelah membaca posting ini Anda akan benar-benar memahami perbedaan antara ini.
ncubica

4
Sangat mengejutkan ! Anda merujuk blog di sini dan keduanya mengatakan hal yang sama sekali berlawanan. Anda mengatakan: Factory - Instantiable - Ya Blog mengatakan: Factory - Instantiable - Tidak
Devesh M

1
Saya setuju dengan @Devesh. Saya pikir Anda memiliki instantiate bercampur. Dari posting blog: "Hanya dengan pabrik, Anda tidak dapat mencapai ini karena pabrik tidak dapat dipakai".
Matt

20

Konsep untuk semua penyedia ini jauh lebih sederhana daripada yang awalnya muncul. Jika Anda membedah penyedia Anda dan menarik bagian-bagian yang berbeda itu menjadi sangat jelas.

Sederhananya masing-masing penyedia ini adalah versi khusus dari yang lain, dalam urutan ini: provider> factory> value/ constant/ service.

Begitu lama penyedia melakukan apa yang Anda bisa, Anda dapat menggunakan penyedia lebih lanjut dalam rantai yang akan menghasilkan lebih sedikit menulis kode. Jika itu tidak mencapai apa yang Anda inginkan, Anda dapat naik rantai dan Anda hanya perlu menulis lebih banyak kode.

Gambar ini menggambarkan apa yang saya maksud, dalam gambar ini Anda akan melihat kode untuk penyedia, dengan bagian-bagian yang disorot menunjukkan kepada Anda bagian mana dari penyedia yang dapat digunakan untuk membuat pabrik, nilai, dll.

Penyedia AngularJS, pabrik, layanan, dll semuanya adalah hal yang sama
(sumber: simplygoodcode.com )

Untuk detail lebih lanjut dan contoh-contoh dari posting blog di mana saya mendapatkan gambar dari pergi ke: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


8

Baik pabrik maupun layanan menghasilkan objek tunggal yang dapat dikonfigurasi oleh penyedia dan disuntikkan ke dalam pengontrol dan menjalankan blok. Dari sudut pandang injectee, sama sekali tidak ada perbedaan apakah objek tersebut berasal dari pabrik atau layanan.

Jadi, kapan menggunakan pabrik, dan kapan menggunakan layanan? Itu bermuara pada preferensi pengkodean Anda, dan tidak ada yang lain. Jika Anda menyukai pola JS modular kemudian pergi ke pabrik. Jika Anda menyukai gaya fungsi konstruktor ("kelas"), pergilah ke layanan. Perhatikan bahwa kedua gaya mendukung anggota pribadi.

Keuntungan dari layanan ini mungkin lebih intuitif dari sudut pandang OOP: membuat "kelas", dan, bersama dengan penyedia, menggunakan kembali kode yang sama di seluruh modul, dan memvariasikan perilaku objek instantiated hanya dengan memasok parameter berbeda ke konstruktor di blok konfigurasi.


Bisakah Anda memberikan contoh apa yang Anda maksudkan dengan memberikan parameter yang berbeda kepada konstruktor di blok konfigurasi? Bagaimana Anda memberikan parameter jika itu hanya layanan atau pabrik. Apa yang Anda maksud dengan "dalam hubungannya dengan penyedia"? Mampu mengkonfigurasinya membuat saya berpikir banyak objek saya harus menjadi penyedia vs pabrik atau layanan.
timbrown

2

Tidak ada yang tidak dapat dilakukan atau dilakukan oleh Pabrik dengan lebih baik dibandingkan dengan Layanan. Dan sebaliknya. Pabrik sepertinya lebih populer. Alasannya adalah kemudahannya dalam menangani anggota pribadi / publik. Layanan akan lebih canggung dalam hal ini. Saat mengkode Layanan, Anda cenderung membuat anggota objek Anda publik melalui kata kunci "ini" dan tiba-tiba mengetahui bahwa anggota publik tersebut tidak terlihat oleh metode pribadi (yaitu fungsi dalam).

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 menggunakan kata kunci "baru" untuk membuat layanan untuk Anda, jadi instance Angular yang lolos ke controller akan memiliki kelemahan yang sama. Tentu saja Anda dapat mengatasi masalah dengan menggunakan ini / itu:

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'  

Tetapi dengan konstanta Layanan yang besar, ini akan membuat kode tersebut terbaca dengan buruk. Selain itu, prototipe Layanan tidak akan melihat anggota pribadi - hanya publik yang akan tersedia untuk mereka:

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'

Ringkasnya, menggunakan Factory lebih nyaman. Karena Factory tidak memiliki kekurangan ini. Saya akan merekomendasikan menggunakannya secara default.


Jawaban ini memiliki beberapa masalah. Pertama, posting ini menunjukkan konsep Javascript tentang pelingkupan leksikal daripada bagaimana layanan AngularJS bekerja. Kedua, konteks panggilan myapp.service(...)tidak ada sama sekali. Di mana new Service()seharusnya dipanggil, dalam fungsi layanan atau di tempat Layanan disuntikkan. Daftar ketiga sama sekali tidak mungkin dalam konteks myapp.service ('Service', function() {...}).
lanoxx

2

Bahkan ketika mereka mengatakan bahwa semua layanan dan pabrik adalah tunggal, saya tidak setuju 100 persen dengan itu. Saya akan mengatakan bahwa pabrik bukan lajang dan ini adalah inti dari jawaban saya. Saya benar-benar akan berpikir tentang nama yang mendefinisikan setiap komponen (Layanan / Pabrik), maksud saya:

Sebuah pabrik karena bukan singleton, Anda dapat membuat sebanyak yang Anda inginkan ketika Anda menyuntikkan, sehingga berfungsi seperti pabrik objek. Anda dapat membuat pabrik entitas domain Anda dan bekerja lebih nyaman dengan objek ini yang bisa seperti objek model Anda. Ketika Anda mengambil beberapa objek, Anda dapat memetakannya di objek ini dan itu dapat bertindak seperti lapisan lain antara DDBB dan model AngularJs. Anda dapat menambahkan metode ke objek sehingga Anda berorientasi ke objek sedikit lebih banyak aplikasi AngularJs Anda.

Sementara itu sebuah layanan adalah singleton, jadi kami hanya dapat membuat 1 jenis, mungkin tidak membuat tapi kami hanya memiliki 1 instance ketika kami menyuntikkan di controller, sehingga layanan menyediakan lebih seperti layanan umum (panggilan istirahat, fungsi ..) ke pengendali.

Secara konseptual Anda dapat berpikir seperti layanan menyediakan layanan, pabrik dapat membuat beberapa instance (objek) kelas


0

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 yang satu ini.


0

Dapat menggunakan kedua cara yang Anda inginkan : apakah membuat objek atau hanya untuk mengakses fungsi dari keduanya


Anda dapat membuat objek baru dari layanan

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();
})

Catatan :

  • layanan secara default mengembalikan objek dan bukan fungsi konstruktor.
  • Jadi itu sebabnya fungsi konstruktor diatur ke properti this.model.
  • Karena layanan ini akan mengembalikan objek, tetapi tetapi di dalam objek itu akan ada fungsi konstruktor yang akan digunakan untuk membuat objek baru;

Anda dapat membuat objek baru dari pabrik

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();
})

Catatan :

  • pabrik secara default mengembalikan fungsi konstruktor dan bukan objek.
  • Jadi itu sebabnya objek baru dapat dibuat dengan fungsi konstruktor.

Buat layanan untuk hanya mengakses fungsi-fungsi sederhana

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

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

Buat pabrik hanya untuk mengakses fungsi sederhana

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()
})

Kesimpulan:

  • Anda dapat menggunakan keduanya seperti yang Anda inginkan apakah akan membuat objek baru atau hanya untuk mengakses fungsi sederhana
  • Tidak akan ada hit kinerja, menggunakan satu di atas yang lain
  • Keduanya adalah objek tunggal dan hanya satu instance yang dibuat per aplikasi.
  • Menjadi hanya satu contoh di mana referensi mereka dilewati.
  • Dalam dokumentasi sudut pabrik disebut layanan dan juga layanan disebut layanan .

0

Pabrik dan Layanan adalah metode yang paling umum digunakan. Satu-satunya perbedaan di antara mereka adalah bahwa metode Layanan berfungsi lebih baik untuk objek yang membutuhkan hierarki warisan, sedangkan Pabrik dapat menghasilkan primitif dan fungsi JavaScript.

Fungsi Penyedia adalah metode inti dan semua yang lain hanya gula sintaksis di atasnya. Anda hanya membutuhkannya jika Anda sedang membangun bagian kode yang dapat digunakan kembali yang membutuhkan konfigurasi global.

Ada lima metode untuk membuat layanan: Nilai, Pabrik, Layanan, Penyedia, dan Konstan. Anda dapat mempelajari lebih lanjut tentang layanan bersudut sini , artikel ini menjelaskan semua metode ini dengan contoh demo praktis.

.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.