AngularJS: когда использовать обслуживание вместо фабрики

пожалуйста, потерпите меня здесь. Я знаю, что есть и другие ответы, такие как: 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()
    ];
}

8 ответов


объяснение

у вас здесь разные вещи:

первый:

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

ref: угловое.сервис vs угловатый.фабрика

второй:

имейте в виду, что все поставщики в AngularJS (value, constant, services, factories) являются синглетами!

третий:

использование одного или другого (service или factory) - это стиль кода. Но ... --8-->распространенным способом в AngularJS использовать завод.

почему ?

, потому что "метод фабрики наиболее распространенный способ получения объектов в систему впрыска зависимостей AngularJS. Он очень гибкий и может содержать сложную логику создания. Поскольку фабрики являются регулярными функциями, мы также можем воспользоваться новой лексической областью для имитации "частных" переменных. Это очень полезно, Так как мы можем скрыть детали реализации данной службы."

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


использование

сервис : может быть полезно для совместного использования функций утилиты, которые полезно вызывать, просто добавляя () к введенной ссылке функции. Также можно запустить с помощью injectedArg.call(this) или аналогичные.

Фабрика : может быть полезно для возврата функции "class", которая затем может быть new'ed для создания экземпляры.

и использовать фабрику, когда у вас есть сложная логика и вы не хотите подвергать эту сложность.

в других случаях если вы хотите вернуть экземпляр службы, просто используйте 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

"если вы хотите, чтобы ваша функция быть вызванным как нормальная функция используйте завод. Если вы хотите, чтобы ваша функция была создана с помощью new оператор, воспользуйтесь услугой. Если вы не знаете разницы, используйте factory."


обновление :

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

и с этой страницы:

"Фабрика и обслуживание наиболее обыкновенно используемые рецепты. Единственное различие между ними заключается в том, что Service recipe лучше работает для объектов пользовательского типа, в то время как Фабрика может производить примитивы и функции JavaScript."


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 в вашем контроллере, проходя в ряде цилиндров, характерных для этого автомобиля. Ты не можешь этого сделать!--7--> потому что CarService-это объект, а не функция.

причина, по которой фабрики не работают так:

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

и автоматически возвращает функцию для создания экземпляра, потому что тогда вы не можете этого сделать это (добавьте вещи в прототип / etc):

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. используйте фабрику когда вам нужно создаю объект, я.новый Клиент (), новый комментарий () и т. д.

  3. провайдер использовать, когда вам нужно настроить его. т. е. проверить URL-адрес, URL-адрес, ОК, производство url-адрес.

если вы обнаружите, что просто возвращаете объект на заводе, вы, вероятно, должны использовать сервис.

Не делайте этого:

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

вместо этого используйте сервис:

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

концепция для всех этих поставщиков намного проще, чем кажется изначально. Если вы препарируете провайдера и вытаскиваете разные части, это становится очень ясно.

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

пока поставщик делает то, что вы можете, вы можете использовать поставщика дальше по цепочке, что приведет к написанию меньше кода. Если это не выполняет то, что вы хотите, вы можете подняться по цепочке, и вам просто нужно написать больше кода.

Это изображение иллюстрирует, что я имею в виду, в этом изображении вы увидите код для поставщика, с выделенными частями, показывающими вам, какие части поставщика могут быть использованы для создания фабрики, значения и т. д.

поставщики AngularJS, фабрики, обслуживания, etc все такая же вещь http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider-service-factory-highlight.png

для получения более подробной информации и примеров из сообщения в блоге, где я получил изображение от go to: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


как фабрика, так и служба приводят к одноэлементным объектам, которые могут быть настроены поставщиками и введены в контроллеры и блоки запуска. С точки зрения инжектора, нет абсолютно никакой разницы, пришел ли объект с завода или службы.

Итак, когда использовать фабрику, и когда использовать услугу? Это сводится к вашему предпочтению кодирования, и ничего больше. Если вам нравится модульный шаблон JS, перейдите на завод. Если вам нравится затем стиль функции конструктора ("класс") переходит к сервису. Обратите внимание, что оба стиля поддерживают частные члены.

преимущество службы может заключаться в том, что она более интуитивно понятна с точки зрения ООП: создайте "класс" и совместно с поставщиком повторно используйте один и тот же код между модулями и изменяйте поведение создаваемых объектов, просто предоставляя различные параметры конструктору в блоке конфигурации.


нет ничего, что фабрика не может сделать или делает лучше по сравнению с сервисом. И наоборот. Фабрика просто кажется более популярной. Причиной этого является его удобство в обращении с частными / публичными членами. В этой связи все более топорно. При кодировании службы вы, как правило, делаете свои члены объекта общедоступными с помощью ключевого слова "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'

Угловое использует ключевое слово " new " для создания службы для вас, поэтому угловые передачи экземпляра контроллеру будут иметь тот же недостаток. Конечно, вы можете преодолеть проблему, используя это/это:

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'  

но с большой константой обслуживания это\that-ing сделало бы код плохо читаемым. Более того, прототипы сервиса не будут видеть частных участников – им будут доступны только публичные:

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'

суммировать его, используя фабрику более удобен. Как фабрика делает не имеют этих недостатков. Я бы рекомендовал использовать его по умолчанию.


даже когда они говорят, что все службы и фабрики являются синглтонами, я не согласен с этим на 100 процентов. Я бы сказал, что фабрики не являются синглетами, и в этом суть моего ответа. Я бы действительно подумал о названии, которое определяет каждый компонент(сервис / Фабрика), я имею в виду:

A завод потому что это не синглтон, вы можете создать столько, сколько вы хотите, когда вы вводите, так он работает как фабрика объектов. Вы можете создать фабрику сущности вашего домен и работать более комфортно с этими объектами, которые могут быть как объект вашей модели. Когда вы получаете несколько объектов, вы можете отобразить их в этих объектах, и это может действовать как другой слой между DDBB и моделью AngularJs.Вы можете добавить методы к объектам, чтобы вы ориентировались на объекты немного больше вашего приложения AngularJs.

тем временем a сервис является синглтоном, поэтому мы можем создать только 1 вид, может быть, не создавать, но у нас есть только 1 экземпляр, когда мы inject в контроллере, поэтому служба предоставляет больше похожую на общую службу (вызовы rest, функциональность.. ) контроллерам.

концептуально вы можете думать, как услуги предоставляют услугу, фабрики могут создавать несколько экземпляров (объектов) класса


услуги

синтаксис: модуль.service ('serviceName', функция ); результат: при объявлении serviceName в качестве вводимого аргумента вам будет предоставлена фактическая ссылка на функцию, переданная модулю.услуга.

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

фабрики

синтаксис: модуль.фабрика( 'factoryName', функция );

результат: при объявлении factoryName в качестве вводимого аргумента вам будет предоставлено значение, которое возвращается путем вызова ссылки на функцию, переданную модулю.фабрика.

использование: может быть полезно для возврата функции "class", которая затем может быть new'ed для создания экземпляры.

поставщики

синтаксис: модуль.provider ('providerName', функция );

результат: при объявлении providerName в качестве вводимого аргумента вам будет предоставлено значение, возвращаемое путем вызова метода $get ссылки на функцию, переданной модулю.поставщик.

использование: может быть полезно для возврата функции "class", которая затем может быть new'ed для создания экземпляров но это требует какой-то конфигурации перед инъекцией. Возможно, полезно для классов, которые повторно используются в проектах? Все еще как в тумане.


можно использовать как как хочешь : ли создать объект или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();
})

Примечание :

  • service по умолчанию возвращает объект, а не функцию конструктора .
  • так вот почему функция конструктора установлена на это.свойство модели.
  • из-за этого сервис вернет объект, но внутри этого объекта будет функция конструктора, которая будет использоваться для создания нового объекта;

вы можете создать новый объект из Фабрики

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

Примечание :

  • factory по умолчанию возвращает функцию конструктора, а не объект.
  • так вот почему новый объект может быть создан с помощью функции конструктора.

создать сервис для простого доступа к простым функциям

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

вывод :

  • можно использовать как хочешь Создавать ли новый объект или просто для доступа к простым функциям
  • не будет никакого хита производительности, используя один над другим
  • оба синглтон объекты и только один экземпляр создается для каждого приложения.
  • будучи только одним экземпляром каждый, где их ссылка передается.
  • в угловой документации фабрика вызвана обслуживанием и сервис называется сервис.