Это то, что помогло мне понять разницу, благодаря сообщению в блоге Паскаля Прехта.
Служба - это метод в модуле, который принимает имя, и функция, которая определяет службу. Вы можете внедрить и использовать этот конкретный сервис в других компонентах, таких как контроллеры, директивы и фильтры. Фабрика - это метод в модуле, который также принимает имя и функцию, которые определяют фабрику. Мы также можем внедрить и использовать его так же, как мы это сделали с сервисом.
Объекты, созданные с помощью new, используют значение свойства prototype их функции конструктора в качестве своего прототипа, поэтому я обнаружил код Angular, который вызывает Object.create (), который, как я считаю, является функцией конструктора службы, когда она создается. Однако фабричная функция - это на самом деле просто вызываемая функция, поэтому мы должны возвращать литерал объекта для фабрики.
Вот угловой код 1.5, который я нашел для фабрики:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
Фрагмент углового исходного кода для функции factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Он принимает имя и фабричную функцию, которые передаются, и возвращает провайдера с тем же именем, у которого есть метод $ get, который является нашей фабричной функцией. Всякий раз, когда вы запрашиваете у инжектора конкретную зависимость, он в основном запрашивает у соответствующего провайдера экземпляр этой службы, вызывая метод $ get (). Вот почему $ get () требуется при создании провайдеров.
Вот угловой код 1.5 для обслуживания.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Оказывается, когда мы вызываем service (), он на самом деле вызывает factory ()! Тем не менее, он не просто передает нашу функцию конструктора сервиса на завод. Он также передает функцию, которая просит инжектор создать объект с помощью данного конструктора.
Другими словами, если мы внедряем MyService где-то, что происходит в коде:
MyServiceProvider.$get(); // return the instance of the service
Чтобы повторить это снова, сервис вызывает фабрику, которая является методом $ get () соответствующего провайдера. Более того, $ injector.instantiate () - это метод, который в конечном итоге вызывает Object.create () с функцией конструктора. Вот почему мы используем «это» в сервисах.
Для ES5 не имеет значения, какой мы используем: service () или factory (), всегда вызывается фабрика, которая создает провайдера для нашего сервиса.
Вы можете сделать то же самое с услугами, хотя. Однако служба - это функция конструктора, которая не мешает нам возвращать объектные литералы. Таким образом, мы можем взять наш сервисный код и записать его так, чтобы он в основном делал то же самое, что и наша фабрика, или, другими словами, вы можете написать сервис как фабрику для возврата объекта.
Почему большинство людей рекомендуют использовать фабрики вместо услуг? Это лучший ответ, который я когда-либо видел, из книги Павла Козловского: освоение разработки веб-приложений с помощью AngularJS.
Фабричный метод является наиболее распространенным способом получения объектов в систему внедрения зависимостей AngularJS. Он очень гибкий и может содержать сложную логику создания. Поскольку фабрики являются регулярными функциями, мы также можем воспользоваться новой лексической областью для моделирования «частных» переменных. Это очень полезно, так как мы можем скрыть детали реализации данного сервиса. "