AngularJS: Коли використовувати сервіс замість фабрики


296

Будь ласка, несіть зі мною тут. Я знаю, що є інші відповіді, такі як: AngularJS: Сервіс проти постачальника проти фабрики

Однак я досі не можу зрозуміти, коли ви користуєтесь сервісом на заводі.

З того, що я можу сказати, фабрика зазвичай використовується для створення "загальних" функцій, які можна викликати декількома контролерами: Створення загальних функцій контролера

Кутові документи віддають перевагу фабриці над сервісом. Вони навіть посилаються на "сервіс", коли використовують фабрику, що ще більше заплутано! http://docs.angularjs.org/guide/dev_guide.services.creating_services

То коли б користуватися послугою?

Чи є щось, що тільки можливо або набагато простіше зробити з сервісом?

Чи є щось інше, що відбувається за лаштунками? Продуктивність / відмінності пам’яті?

Ось приклад. Окрім методу декларування, вони здаються однаковими, і я не можу зрозуміти, чому я став би один проти іншого. http://jsfiddle.net/uEpkE/

Оновлення: З відповіді Томаса, мабуть, випливає, що сервіс призначений для більш простої логіки та для більш складної логіки з приватними методами, тому я оновив код скрипку нижче, і здається, що обидва здатні підтримувати приватні функції?

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

Звичайно, сервіс підтримує приватне, але якщо ви правильно прочитали мою публікацію, це суто стиль коду: ми також можемо скористатися новою лексичною сферою для імітації "приватних" змінних. Це "SIMULATE"
Thomas Pons

Я вважаю цю дискусію дуже корисною stackoverflow.com/questions/15666048/…
Anand Gupta

Відповіді:


280

Пояснення

Тут у вас є різні речі:

Спочатку:

  • Якщо ви користуєтесь послугою, ви отримаєте екземпляр функції (" this" ключового слова).
  • Якщо ви використовуєте фабрику, ви отримаєте значення, яке повертається, викликаючи посилання на функцію (оператор return на заводі).

ref: angular.service vs angular.factory

Друге:

Майте на увазі, що всі постачальники в AngularJS (вартість, константа, послуги, фабрики) - одинаки!

Третє:

Використання одного чи іншого (сервісного чи фабричного) стосується стилю коду. Але загальним способом в AngularJS є використання фабрики .

Чому?

Оскільки "заводський метод - це найпоширеніший спосіб потрапляння об'єктів в систему введення залежності залежної форми AngularJS. Він дуже гнучкий і може містити складну логіку створення. Оскільки фабрики є регулярними функціями, ми також можемо скористатися новою лексичною сферою для імітації" приватної "змінні. Це дуже корисно, оскільки ми можемо приховати деталі реалізації даної послуги."

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


Використання

Сервіс: Може бути корисним для спільного використання функцій утиліти, які корисно викликати, просто додавши ()до введеної посилання функції. Може також працювати з injectedArg.call(this)подібним або подібним.

Фабрика: Може бути корисною для повернення функції "class", яка потім може бути новою "для створення примірників.

Отже, використовуйте фабрику, коли у вашій службі є складна логіка і ви не хочете піддавати цій складності .

В інших випадках, якщо ви хочете повернути екземпляр послуги, просто скористайтеся сервісом .

Але з часом ви побачите, що в 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

"Якщо ви хочете, щоб ваша функція називалася як звичайна функція , використовуйте фабрику . Якщо ви хочете, щоб ваша функція була інстанцірована з новим оператором, скористайтеся сервісом. Якщо ви не знаєте різниці, використовуйте фабрику."


ОНОВЛЕННЯ:

Команда AngularJS виконує свою роботу та дає пояснення: http://docs.angularjs.org/guide/providers

І з цієї сторінки:

"Фабрика та Сервіс - це найчастіше використовувані рецепти. Єдина відмінність між ними полягає в тому, що рецепт Сервісу працює краще для об'єктів користувацького типу, тоді як Фабрика може створювати примітиви та функції JavaScript."


7
По-перше: я читав це скрізь, але не розумію його практичних наслідків. Я думаю, що з вашої відповіді немає практичної різниці "здебільшого"? Дякуємо за книжкову реф.
користувач1941747

Це просто, якщо ваша послуга дійсно складна і вам потрібні приватні методи та об’єкти, які використовують фабрику
Thomas Pons

1
Я помітив, що ви додали "Якщо ви хочете повернути екземпляр послуги, просто скористайтеся сервісом". Моє подальше запитання було б, КОЛИ ви хочете повернути примірник послуги? Я намагаюся знайти конкретний випадок використання тут.
користувач1941747

12
"Оскільки фабрики є регулярними функціями, ми також можемо скористатися новою лексичною сферою для імітації" приватних "змінних". - це не стосується фабрик, ви можете зробити те ж саме з послугами ..
pootzko

Здається, команда google надає перевагу сервісному обслуговуванню над фабрикою, це робить речі ще більш заплутаними! google-styleguide.googlecode.com/svn/trunk/…
xzhang

111

Спочатку alernhwkim опублікував відповідь на це питання, посилаючись на свій блог , проте модератор видалив його. Це єдиний знайдений мною пост, який не просто розказує вам, як зробити те ж саме з сервісом, постачальником та фабрикою, але також розповідає, що ви можете зробити з постачальником, який ви не можете на заводі та з фабрика, яку ви не можете забезпечити сервісом.

Безпосередньо з його блогу:

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 CarServiceтому що CarService є об'єктом, а не функцією.

Причини, що фабрики не працюють так:

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} Кодувати це легко, але ви не можете його створити.

  2. Використовуйте Factory, коли потрібно створити об'єкт, тобто новий Клієнт (), Новий коментар () тощо.

  3. Використовуйте Провайдера, коли вам потрібно його налаштувати. тобто URL-адреса тесту, URL-адреса якості, URL-адреса виробництва.

Якщо ви виявили, що ви просто повертаєте об'єкт на заводі, ви, ймовірно, повинні скористатися сервісом.

Не робіть цього:

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

Використовуйте сервіс замість цього:

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

11
це дуже корисно для мене +1 для таблиці порівняння
Vu Anh

5
якщо ви визначаєте службову функцію одним параметром numCylinder, вона матиме таку ж гнучкість, що і заводський метод
Ovi

заходьте і читайте пост в блозі, і витрачайте час на те, щоб розібратися у кутовому, якщо ви знаєте, що після прочитаного цього повідомлення javascript ви зрозумієте різницю між цим.
ncubica

4
Дуже здивований! Ви тут посилаєтесь на блог, і обидва говорять зовсім протилежне. Ви кажете: Фабрика - Моментальна - Так, що в блозі кажуть: Фабрика - Неподільна - Ні
Devesh M

1
Я згоден з @Devesh. Я думаю, що у вас змішані інстанції. З допису в блозі: "Тільки з фабрикою ви цього не можете досягти, тому що завод не може бути створений".
Мт

20

Концепція для всіх цих провайдерів набагато простіша, ніж спочатку представляється. Якщо ви розсікаєте постачальника, ви витягуєте різні частини, це стає дуже зрозумілим.

Простіше кажучи , кожен з цих провайдерів є спеціалізованою версією іншого, в наступному порядку: provider> factory> value/ constant/ service.

Поки провайдер робить те, що ви можете, ви можете скористатися провайдером далі по ланцюгу, що призведе до написання менше коду. Якщо він не здійснить те, що ви хочете, можете піднятися по ланцюгу, і вам просто доведеться написати ще код.

Це зображення ілюструє те, що я маю на увазі, на цьому зображенні ви побачите код постачальника, причому частини виділені, що показують, які частини постачальника можна використовувати для створення фабрики, значення тощо.

Провайдери AngularJS, фабрики, послуги тощо - це одне і те ж
(джерело: простоgoodcode.com )

Для отримання більш детальної інформації та прикладів із публікації в блозі, звідки я отримав зображення, перейдіть на сторінку: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


8

Як фабрика, так і сервіс призводять до однотонних об'єктів, які можуть бути налаштовані постачальниками та введені в контролери та запущені блоки. З точки зору ін'єкції, абсолютно немає різниці, чи прийшов об'єкт із заводу чи служби.

Отже, коли користуватися фабрикою, а коли користуватися послугою? Це зводиться до ваших переваг кодування, і нічого іншого. Якщо вам подобається модульний візерунок JS, тоді йдіть на завод. Якщо вам подобається стиль функції конструктора («клас»), тоді перейдіть до служби. Зауважте, що обидва стилі підтримують приватних членів.

Перевага сервісу може полягати в тому, що з точки зору OOP це більш інтуїтивно зрозуміло: створити "клас" і спільно з провайдером повторно використовувати один і той же код через модулі та змінити поведінку об'єктів, що інстанціюються, просто надаючи різні параметри для конструктора в блоці config.


Чи можете ви навести приклад того, що ви маєте на увазі, надаючи конструкторам різні параметри в блоці конфігурацій? Як вказати параметри, якщо це лише послуга чи фабрика. Що ви маєте на увазі під "спільно з провайдером"? Вміючи налаштувати, це змушує мене думати, що багато моїх об'єктів мають бути постачальниками порівняно з фабриками чи послугами.
тембровий

2

Ніщо, що Фабрика не може зробити або зробити краще, порівняно зі Службою. І віце-вірш. Фабрика просто здається більш популярною. Причиною цього є його зручність в роботі з приватними / публічними членами. У цьому плані обслуговування було б більш незграбним. Коли кодуєш Службу, ти, як правило, оприлюднює членів об’єкта за допомогою цього ключового слова та може раптом виявити, що ці публічні члени не бачать приватні методи (тобто внутрішні функції).

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'  

Але при великій постійній службі це \ що-ін зробить код погано читабельним. Більше того, прототипи Сервісу не бачитимуть приватних членів - лише публічні доступні для них:

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. Оскільки у Фабрики немає цих недоліків. Я б рекомендував використовувати його за замовчуванням.


Ця відповідь має кілька проблем. По-перше, ця публікація демонструє концепцію Javascript щодо лексичного визначення, а не того, як працюють сервіси AngularJS. По-друге, контекст дзвінка myapp.service(...)повністю відсутній. Там, де new Service()передбачається викликати, у службовій функції або в місці, де Служба вводиться. Третій перелік просто неможливий у контексті myapp.service ('Service', function() {...}).
lanoxx

2

Навіть коли вони кажуть, що всі послуги та фабрики є однотонними, я не згоден з цим на 100 відсотків. Я б сказав, що фабрики не є однотонними, і це сенс моєї відповіді. Я б дійсно задумався над назвою, яке визначає кожен компонент (Service / Factory), я маю на увазі:

Завод , тому що це не Сінглтон, ви можете створити стільки , скільки ви хочете , коли ви прийдете, так що він працює як фабрика об'єктів. Ви можете створити фабрику юридичної особи свого домену і зручніше працювати з цими об'єктами, які можуть бути схожими на предмет вашої моделі. Коли ви отримуєте кілька об'єктів, ви можете відобразити їх у цих об'єктах, і це може діяти як би інший шар між DDBB і моделлю AngularJs. Ви можете додати методи до об'єктів, щоб ви орієнтувались на об'єкти трохи більше вашого AngularJs App.

Тим часом сервіс є однотонним, тому ми можемо створити лише 1 тип, можливо, не створити, але у нас є лише 1 екземпляр, коли ми вводимо в контролер, тому служба надає більше схожий на загальну службу (дзвінки відпочинку, функціональність ..) до контролерів.

Концептуально можна думати, як послуги надають послугу, фабрики можуть створювати кілька примірників (об’єктів) класу


0

Послуги

Синтаксис : module.service ('serviceName', функція); Результат : При оголошенні serviceName як аргументу, який можна ввести, вам буде надано фактичне посилання функції, передане на module.service.

Використання : Може бути корисним для спільного використання функцій утиліти, які корисно викликати, просто додавши () до введеної посилання функції. Можна також запустити за допомогою injectedArg.call (це) або подібне.

Заводи

Синтаксис : module.factory ('factoryName', функція);

Результат : При оголошенні factoryName як аргументу, який можна вводити, вам буде надано значення, яке повертається, викликаючи посилання на функцію, передану на module.factory.

Використання : Може бути корисним для повернення функції "class", яка потім може бути new'ed для створення примірників.

Постачальники

Синтаксис : module.provider ('providerName', функція);

Результат : При оголошенні providerName як аргументу, який можна вводити, вам буде надано значення, яке повертається, викликаючи метод $ get посилання функції, передане на module.provider.

Використання : Може бути корисним для повернення функції "class", яка потім може бути new'ed для створення примірників, але для введення потрібна певна конфігурація. Можливо, корисно для занять, які можна використовувати повторно в проектах? На цьому все-таки каламутна.


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

Висновок:

  • ви можете використовувати як потрібне, чи створити новий об’єкт, чи просто отримати доступ до простих функцій
  • Не буде жодного хіта на продуктивність, використовуючи один над іншим
  • Обидва є однотонними об'єктами, і лише один екземпляр створюється на додаток.
  • Будучи лише одним екземпляром кожного, де передається їх посилання.
  • У кутовій документації завод називається сервісом, а також сервіс називається сервісом .

0

Фабрика та сервіс - це найбільш часто використовуваний метод. Єдина відмінність між ними полягає в тому, що метод Сервісу працює краще для об'єктів, які потребують ієрархії успадкування, тоді як Фабрика може виробляти примітиви та функції JavaScript.

Функція Провайдера - це основний метод, а всі інші - це лише синтаксичний цукор. Він потрібен лише в тому випадку, якщо ви будуєте багаторазовий фрагмент коду, який потребує глобальної конфігурації.

Існує п'ять методів створення служб: Value, Factory, Service, Provider і Constant. Ви можете дізнатись більше про це тут, кутовий сервіс , ця стаття пояснює всі ці методи на практичних демонстраційних прикладах.

.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.