서비스 대 팩토리에 대한 혼란


618

알다시피, 공장 내부에서는 컨트롤러에 주입되는 물체를 반환합니다. 서비스 내부에서 나는 this아무것도 사용 하지 않고 객체를 사용 하고 있습니다.

나는 서비스가 항상 singleton 이라고 가정하고 모든 컨트롤러에 새로운 팩토리 객체 가 주입 된다고 가정했다 . 그러나 팩토리 객체도 싱글 톤입니까?

설명하는 예제 코드 :

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

변경하는 경우 user.firstACtrl그것을 밝혀 user.first에서이 BCtrl예는,도 변경됩니다 User싱글인가?

내 가정은 공장이있는 컨트롤러에 새 인스턴스가 주입되었다는 것입니까?


4
"module.service"및 "module.factory"옆에는 AngularJS에서 서비스를 작성하는 두 가지 방법이 더 있습니다. 자세한 내용은 블로그 게시물을 참조하십시오 : " 4 가지 다른 방법으로 AngularJS 서비스를 만드는 방법 (싱글 톤) "
Emil van Galen

답변:


600

모든 각도 서비스는 싱글 톤입니다 .

문서 ( 싱글 톤으로 서비스 참조 ) : https://docs.angularjs.org/guide/services

마지막으로 모든 Angular 서비스는 응용 프로그램 싱글 톤임을 인식하는 것이 중요합니다. 이는 인젝터 당 지정된 서비스 인스턴스가 하나만 있음을 의미합니다.

기본적으로 서비스와 공장의 차이점은 다음과 같습니다.

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 + "!";
    }
  }
});

$ provide에 대한이 프레젠테이션을 확인하십시오 : http://slides.wesalvaro.com/20121113/#/

이 슬라이드는 AngularJs 모임 중 하나에서 사용되었습니다 : http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html


13
서비스, ​​공장 및 제공의 차이점을 설명하는 stackoverflow.com/questions/15666048/… 도 참조하십시오 .
Mark Rajcok

31
공식 문서는 간접적으로 [sic! 충분하지 않음]은 팩토리를 사용하여 서비스를 정의하더라도 한 번만 생성됨을 의미합니다. 즉, 참조 (사출 지점)에 따라 다시 생성되지 않습니다. 두 가지 방법 모두 인젝터 당 단일 인스턴스를 생성합니다.
honzajde 2013 년

3
"서비스는 단지 'new'로 호출되는 생성자 함수"라고 말하지만 오해의 소지가 있다고 생각합니다. 나는 그것이 무대 뒤에서 새로운 것으로 불린다 고 생각하지 않는다. 나는 개발자가 new그것을 불러야 할 책임이 있다고 생각 한다.
Tim Kindberg 14

5
@nfiniteloop, 라인 3574 근처에서 소스 코드를 확인하십시오. 팩토리는 제공자의 $ get 메소드이며, 서비스는 제공된 함수에서 $ injector.instantiate를 호출 한 다음 new를 호출하는 메소드를 사용하여 팩토리를 생성합니다. ( 문서 참조 )
citizenslave

14
나는 서비스가 당신이 그것을 참조함으로써 사용했던 싱글 톤이라는 인상을 받았다. 그리고 팩토리는 매번 새로운 객체를 반환하는 싱글 톤이었습니다. 즉, 서비스는 하나의 "차"를 제공하고 프로젝트의 모든 것이이 차를 사용합니다. 공장은 공장을 호출 할 때마다 새 차를 줄 것입니다. 하나는 싱글 톤을 반환 한 싱글 톤이고 다른 하나는 객체를 반환 한 싱글 톤이었습니다. 누구든지 설명 할 수 있습니까? 단일 항목을 호출하는 것은 여러 가지를 참조 할 수 있으므로 도움이되지 않습니다.
user2483724

380

나를 위해 계시는 그들이 모두 같은 방식으로 작동한다는 것을 깨달았을 때 나타났습니다. 무언가를 한 번 실행하고 얻은 값을 저장 한 다음 Dependency Injection을 통해 참조 할 때 동일한 저장된 값 을 기침합니다 .

우리가 가지고 있다고합시다.

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

세 가지의 차이점은 다음과 같습니다.

  1. a저장된 값은 running fn에서 나온다 .fn()
  2. b저장된 값은 newing 에서 가져옵니다 fn. 즉,new fn()
  3. c저장된 값은 new먼저을 호출 하여 인스턴스를 fn가져온 다음 $get인스턴스 의 메소드 를 실행 하여 발생합니다.

즉, 각도 내부에 캐시 객체와 같은 것이 있는데, 각 분사의 값은 처음 분사 될 때 한 번만 할당되며 어디서 :

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

이것이 우리 this가 서비스에서 사용 this.$get하고 공급자를 정의하는 이유 입니다.

도움이 되었기를 바랍니다.


54
마지막으로 제정신의 설명. 앵귤러는 미쳐서 완전히 나빠서 아파요.
osiris

8
실제로 WHY 공장, 서비스 및 공급자가 단일 값을 반환하는 문제에 대한 답변이므로 허용되는 답변이어야합니다. 다른 답변은 공장, 서비스 및 공급자 간의 차이점을 설명하지만 싱글 톤 측면은 절대 다루지 않습니다.
wmock

3
나는 이것을 좋아한다 ... 다른 블로거로부터 수천 줄의 문장을 읽을 때 .. 나는 단지 공장을 이해해야한다. 그러나 나는 이것을 읽었다. 나는 3을 모두 이해한다.
tsohtan

@osiris 동의합니다. 나는 그것을 좋아하지 않는다. 그것은 엄청나게 괴물처럼 느껴져서 내 이빨을 갈게 만듭니다.
토마스

2
공급자를 사용할 때 $ get 구현을 제공해야합니까?
Victor

95

라이브 예

"hello world"예

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

57

당신이 돌아갈 수 있도록 생성자 함수를 반환하는 방법도있다 newable 과 같이 공장에서 클래스 :

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

따라서 MyObjectWithParam을 사용하는 컨트롤러에서이를 수행 할 수 있습니다.

var obj = new MyObjectWithParam("hello"),

전체 예를 보려면 여기를 참조하십시오 :
http://plnkr.co/edit/GKnhIN?p=preview

그리고 여기에 토론 된 Google 그룹 페이지 :
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ


귀하의 예를 사용하여 축소에 문제가 있습니다. 내가 어떻게 주석을 달아야하는지 알고 있습니까?
Pål

2
예, Angular에 대한 축소 표기법이 있습니다. 다음과 같아야합니다. App.factory('MyObjectWithParam', ['$injector', function ($injector) { return function(name) { return $injector.instantiate(MyObjectWithParam,{ name: name }); }; }]); 여기에서 자세히 알아보십시오 : docs.angularjs.org/tutorial/step_05
JustGoscha

4
.service대신 사용할 수 있다면 왜 이렇게 하시겠습니까?
flup

나는 같은 생각을 @flup했다. @justgoscha, 일부 혜택 (가 percieved? 사용) .factory에 반대는 .service?
1

5
서비스는 싱글 톤 이기 때문에 생각 합니다. 내가 여기서 구성한 것은 기본적으로 새로운 클래스 입니다. 당신이 다음 자동차 서비스 공장 같은 것을 가지고 수 있도록 new Car('BMW')하고 new Car('Ford')그들은 같은 변수와 모든 것을 공유하지 않습니다.
JustGoscha

51

주요 차이점은 다음과 같습니다.

서비스

통사론: module.service( 'serviceName', function );

결과 : serviceName을 주사 가능한 인수로 선언하면에 전달 된 함수인스턴스 가 제공 됩니다 module.service.

사용법 : 주입 된 함수 참조에 단순히 ()를 추가하여 호출하는 데 유용한 유틸리티 함수공유하는 데 유용 할 수 있습니다 . 함께 injectedArg.call( this )또는 유사 하게 실행할 수 있습니다 .

공장

통사론: module.factory( 'factoryName', function );

결과 : factoryName을 주입 가능한 인수로 선언하면에 전달 된 함수 참조를 호출하여 리턴되는 값이 제공 됩니다 module.factory.

사용법 : 인스턴스를 만들기 위해 새로 만들 수 있는 '클래스' 기능 을 반환하는 데 유용 할 수 있습니다 .

또한 서비스 대 팩토리에 대해 혼란스러워하는 Stackoverflow에 대한 AngularJS 문서 및 유사한 질문을 확인하십시오 .

다음은 services 및 factory를 사용하는 예 입니다. AngularJS 서비스와 팩토리 에 대해 자세히 읽어보십시오 .


6
이것은 나에게 의미가 있습니다. 팩토리는 새 객체를 만들기위한 청사진을 반환합니다.

27

첫 번째 대답에 덧붙여서, .service ()는 코드를 더 객체 지향 스타일 (C # / Java)로 작성한 사람들 (이 키워드를 사용하고 프로토 타입 / 생성자 함수를 통해 객체를 인스턴스화하는 사람들)을위한 것이라고 생각합니다.

팩토리는 자바 스크립트 / 기능적 스타일의 코딩에 더 자연스러운 코드를 작성하는 개발자를위한 것입니다.

angular.js 내부의 .service 및 .factory 메소드의 소스 코드를 살펴보십시오. 내부적으로 모두 제공자 메소드를 호출합니다.

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

25

아주 간단하게 :

.service-등록 된 함수는 생성자 (일명 '신규')로 호출됩니다.

.factory-등록 된 함수는 간단한 함수로 호출됩니다.

둘 다 한 번 호출되어 단일 객체가 생성되어 앱의 다른 구성 요소에 주입됩니다.


6
예. 실제보다 더 복잡하게 만들지 마십시오
flup

20

모든 제공자는 같은 방식으로 일합니다. 서로 다른 방법 service, factory,provider 당신이 더 적은 코드에서 같은 일을 수행 할 수 있습니다.

PS도 있습니다 valueconstant .

체인으로 시작 provider하고 끝나는 각각의 특별한 경우value 에는 추가 제한이 있습니다. 따라서 그들 사이를 결정하려면 적은 코드로 원하는 것을 달성 할 수 있는지 스스로에게 물어보십시오.

여기에 내가 무슨 뜻인지 보여주는 그림이 있습니다.

여기에 이미지 설명을 입력하십시오

이 이미지를 얻은 블로그 게시물에서 분류 및 참조 안내서를 사용할 수 있습니다.

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


서비스는 싱글 톤이라고 말하지만, 매번 새로운 인스턴스가 생성 될 때마다 싱글 톤은 어떻게됩니까?
Ankur Marwaha

1
@AnkurMarwaha 새로운 인스턴스는 매번 생성되지 않으며 AngularJS에 의해 한 번만 생성되고 캐시됩니다. 공급자, 공장, 서비스 등을 사용하고 있는지 여부에 관계없이 적용 console.log()됩니다. 여러 컨트롤러를 사용 하여 주입 하여 이를 확인할 수 있습니다 .
Luis Perez

Luis, 귀하의 의견은 허용 된 답변과 충돌합니다. 마지막으로 모든 Angular 서비스가 응용 프로그램 싱글 톤임을 인식하는 것이 중요합니다. 이는 인젝터 당 지정된 서비스 인스턴스가 하나만 있음을 의미합니다.
Ankur Marwaha

@ AnkurMarwaha 어쩌면 내가 오해하고있을 것입니다. "모든 Angular 서비스가 응용 프로그램 싱글 톤임을 인식하는 것이 중요합니다"라고 인용했습니다. 싱글 톤이라는 사실은 서비스가 한 번만 생성됨을 의미합니다. "새 인스턴스 매번 생성 되지 않으며 한 번만 생성되고 캐시됩니다 ..."라고 말했습니다. 갈등이 보이는 부분을 더 자세히 지적 할 수 있습니까?
Luis Perez

1
아, 혼란을 봅니다. "인젝터"는 각도의 객체입니다. "주사"를 담당합니다. 예를 들어, 컨트롤러가 처음 실행될 때 "인젝터"는 매개 변수를보고 각각을 주입합니다. 전체 앱에는 "인젝터"가 하나만 있습니다. 인젝터가 특정 팩토리 또는 서비스를 생성하면 인스턴스를 유지하고 재사용하므로 싱글 톤입니다. 따라서 앱당 하나의 인젝터와 인젝터 당 하나의 지정된 서비스 인스턴스 만 있습니다. 대부분의 Angular 응용 프로그램에는 하나의 응용 프로그램 만 있으므로 하나의 인젝터, 따라서 모든 서비스, 컨트롤러 등의 인스턴스가 있습니다.
Luis Perez

13

다음은 서비스와 팩토리의 차이를 보는 데 유용한 몇 가지 서비스와 팩토리의 예입니다. 기본적으로 서비스에는 "새로운 ..."이 있으며 이미 인스턴스화되어 있습니다. 팩토리는 자동으로 인스턴스화되지 않습니다.

기본 예

단일 메소드를 가진 클래스 객체를 반환

단일 방법이있는 서비스는 다음과 같습니다.

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

다음은 메소드를 사용하여 객체를 반환하는 팩토리입니다.

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

값을 반환

숫자 목록을 반환하는 팩토리 :

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

console.log(NumberListFactory);

숫자 목록을 반환하는 서비스 :

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

console.log(NumberLister.numbers);

두 경우의 결과는 숫자 목록과 동일합니다.

고급 예

팩토리를 사용하는 "클래스"변수

이 예제에서는 CounterFactory를 정의하고 카운터를 늘리거나 줄이며 현재 카운트를 얻거나 작성된 CounterFactory 객체 수를 얻을 수 있습니다.

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

})

우리는 CounterFactory여러 카운터를 만드는 데 사용 합니다. 클래스 변수에 액세스하여 생성 된 카운터 수를 확인할 수 있습니다.

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

이 코드의 출력은 다음과 같습니다.

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

유용한 예입니다. number_of_counter_factories는 CounterFactory 클래스의 메타 속성과 같습니다. 맞습니까?이 예제가 서비스에서 복제 가능하다는 것을 이해합니다 (잘못되면 알려주세요).이 경우 의미 론적 차이는 무엇입니까?
geoom

유용한 예! 이것은 기본적으로 팩토리에서 서비스에 들어 가지 않을 추가 추상화 계층을 가질 수 있음을 의미합니다. 그러나 반환 된 것이 무엇이든, 'new'가 사용될 때마다 새로운 인스턴스가 반환됩니다. 리턴 블록 내에 선언되지 않은 모든 변수는 싱글 톤입니다. 내가 알았어?
Swanidhi

@Swanidhi 기본적으로 그렇습니다. 공장에서 싱글 톤 인 변수를 선언 할 수 있습니다. 그래서 나는 이것을 "클래스"변수라고 불렀습니다.

13

"공장"및 "서비스"는 각도로 DI (종속 주입)를 수행하는 다른 방법입니다.

아래 코드와 같이“service”를 사용하여 DI를 정의 할 때 이것은 "Logger"오브젝트의 새로운 GLOBAL 인스턴스를 작성하고이를 함수에 삽입합니다.

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

"공장"을 사용하여 DI를 정의하면 인스턴스가 생성되지 않습니다. 메소드를 전달하면 나중에 소비자는 내부적으로 팩토리를 호출하여 객체 인스턴스를 호출해야합니다.

app.factory("Customerfactory", CreateCustomer);

아래는 "서비스"에 대한 DI 프로세스가 "공장"과 어떻게 다른지 시각적으로 보여주는 간단한 이미지입니다.

여기에 이미지 설명을 입력하십시오

팩토리를 사용해야합니다 시나리오에 따라 다른 유형의 오브젝트를 작성하려고 할 때. 예를 들어 시나리오에 따라 간단한 "고객"개체 또는 "주소"개체로 "고객"또는 "전화"개체로 "고객"을 만들려고합니다. 이 단락에 대한 자세한 설명은 다음과 같습니다.

Utility, Logger, Error handler 등과 같이 유틸리티 또는 공유 기능을 주입 할 때 서비스를 사용해야합니다.


이 질문에서 보았던 모든 대답과 유사한 다른 사람들은 역학과 구문의 차이를 지정합니다. 이 답변은 왜 당신이 다른 것을 선택해야하는지에 대한 진정한 이유를 제공합니다. 그것은 의미론의 문제이며 이름, 서비스 또는 공장을보고 그들의 목적과 사용법을 알려줍니다.
Joe Mayo

8

서비스 스타일 : ( 아마도 가장 간단한 것 )은 실제 함수를 반환합니다. 주입 된 함수 참조에 단순히 ()를 추가하여 호출하는 데 유용한 유틸리티 함수를 공유하는 데 유용합니다.

AngularJS의 서비스는 일련의 함수를 포함하는 단일 JavaScript 객체입니다.

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

});

팩토리 스타일 : ( 보다 복잡하지만 더 복잡한 ) 함수의 반환 값을 반환합니다 : java에서 new Object ()와 같은 객체를 인스턴스화하십시오.

팩토리는 값을 생성하는 함수입니다. 서비스, ​​컨트롤러 등이 공장에서 투입된 가치를 필요로 할 때, 공장은 수요에 따라 가치를 창출합니다. 일단 생성되면, 값은 주입이 필요한 모든 서비스, 컨트롤러 등에 재사용됩니다.

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

});

프로 바이더 스타일 : ( full blown, configurable version )은 함수 $ get 함수의 출력을 Configurable로 반환합니다.

AngularJS의 공급자는 가장 유연한 공장 형태입니다. 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


2

기본적인 차이점은 공급자 가 프리미티브 (객체가 아닌), 배열 또는 콜백 함수 값을 팩토리 선언 변수로 설정할 수 있다는 점입니다. 따라서 객체를 반환하는 경우 명시 적으로 선언하고 반환해야합니다.

반면에 서비스 는 서비스 선언 변수를 객체로 설정하는 데만 사용할 수 있으므로 객체를 명시 적으로 생성하고 반환하는 것을 피할 수 있으며 반면에 this 키워드를 사용할 수 있습니다 .

또는 간단히 말해서 " 서비스 제공자 는보다 일반적인 형태이며 서비스 는 객체로만 제한됩니다".


2

이것이 디자인 패턴 측면에서 차이점을 이해하는 방법입니다.

서비스 : 해당 유형의 객체를 만들기 위해 새로워 질 유형을 반환합니다. Java 유추가 사용되는 경우 Service는 Java 클래스 정의를 반환합니다 .

Factory : 즉시 사용할 수있는 콘크리트 객체를 반환합니다. 자바 비유에서 팩토리는 자바 객체를 반환한다 .

사람들 (혼자 포함)을 혼란스럽게하는 부분은 코드에 서비스 나 팩토리를 삽입 할 때 같은 방식으로 사용할 수 있다는 것입니다. 두 경우 모두 코드에서 얻는 것은 즉시 호출 할 수있는 구체적인 객체입니다. 이는 서비스의 경우 서비스를 대신하여 서비스 선언에서 "신규"를 호출한다는 의미입니다. 나는 이것이 복잡한 개념이라고 생각합니다.


1

이것은 Service Vs Factory Vs Provider를 이해하는 데 가장 적합하고 짧은 답변입니다.

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

여기에 데모로 말하는 것은 http://jsbin.com/ohamub/1/edit?html,output

"코드에 주요 차이점을 설명하는 주석이 있지만 여기서 조금 더 확장 할 것입니다. 참고로,이 문제를 해결하기 위해 노력하고 있습니다. 잘못된 것을 말하면 알려주십시오.

서비스

구문 : module.service ( 'serviceName', function);

결과 : serviceName을 주입 가능한 인수로 선언하면 module.service에 전달 된 실제 함수 참조가 제공됩니다.

사용법 : 주입 된 함수 참조에 단순히 ()를 추가하여 호출하는 데 유용한 유틸리티 함수를 공유하는 데 유용 할 수 있습니다. injectionArg.call (this) 또는 이와 유사한 방식으로 실행할 수도 있습니다.

공장

구문 : module.factory ( 'factoryName', function);

결과 : factoryName을 삽입 가능한 인수로 선언하면 module.factory에 전달 된 함수 참조를 호출하여 리턴되는 값이 제공됩니다.

사용법 : 인스턴스를 만들기 위해 새로 만들 수있는 '클래스'함수를 반환하는 데 유용 할 수 있습니다.

공급자

구문 : module.provider ( 'providerName', function);

결과 : providerName을 삽입 가능한 인수로 선언하면 module.provider에 전달 된 함수 참조의 $ get 메소드를 호출하여 리턴되는 값이 제공됩니다.

사용법 : 인스턴스를 만들기 위해 새로 만들 수 있지만 주입되기 전에 일종의 구성이 필요한 '클래스'함수를 반환하는 데 유용 할 수 있습니다. 프로젝트 전체에서 재사용 할 수있는 클래스에 유용할까요? 아직도 이것에 헷갈려. "벤


1

나는 잠시 동안이 혼란을 겪었고 여기에 간단한 설명을 제공하기 위해 최선을 다하고 있습니다. 이것이 도움이되기를 바랍니다!

angular .factory그리고 angular .service모두 동일한 방식으로 서비스와 작업을 초기화하는 데 사용됩니다.

유일한 차이점은 서비스 초기화 방법입니다.

둘 다 싱글 톤입니다


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


공장

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

리턴 값이있는 함수 에서 서비스를 초기화 하려면이 factory메소드 를 사용해야합니다 .

예 :

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

app.factory('myService', myService);

이 서비스를 주입 할 때 (예 : 컨트롤러에) :

  • Angular는 주어진 함수 ( )를 호출 하여 myService()객체를 반환합니다
  • 싱글 톤 -한 번만 호출되어 저장되고 동일한 객체를 전달합니다.


서비스

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

키워드를 사용하여 생성자 함수 에서 서비스를 초기화 this하려면이 service방법 을 사용해야합니다 .

예 :

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

app.service('myService', myService);

이 서비스를 주입 할 때 (예 : 컨트롤러에) :

  • Angular는 new주어진 함수 ( new myService())를 사용하여 객체를 반환합니다.
  • 싱글 톤 -한 번만 호출되어 저장되고 동일한 객체를 전달합니다.


참고 : 사용하는 경우 factory<constructor function>또는 service함께 <function with a return value>, 그것은 작동하지 않습니다.


예-데모


1

Pascal Precht의 블로그 게시물 덕분에 이것이 차이점을 이해하는 데 도움이되었습니다.

서비스는 이름과 서비스를 정의하는 기능을 취하는 모듈의 메소드입니다. 컨트롤러, 지시문 및 필터와 같은 다른 구성 요소에 특정 서비스를 주입하고 사용할 수 있습니다. 팩토리는 모듈의 메소드이며 팩토리를 정의하는 이름과 기능도 사용합니다. 또한 서비스와 동일한 방식으로 주입하여 사용할 수 있습니다.

new로 만든 객체는 생성자 함수의 prototype 속성 값을 프로토 타입으로 사용하므로 Object.create ()를 호출하는 Angular 코드를 찾았습니다. 인스턴스화 될 때 서비스 생성자 함수라고 생각합니다. 그러나 팩토리 함수는 실제로 호출되는 함수일 뿐이므로 팩토리에 대한 객체 리터럴을 반환해야합니다.

공장에서 찾은 각도 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 ()를 호출하는 메소드입니다. 이것이 우리가 서비스에서 "this"를 사용하는 이유입니다.

ES5의 경우 service () 또는 factory () 중 어느 것을 사용하든 상관없이 항상 서비스 팩토리를 만드는 팩토리입니다.

서비스에서도 똑같은 일을 할 수 있습니다. 그러나 서비스는 생성자 함수이지만 객체 리터럴을 반환하지 못하게합니다. 따라서 서비스 코드를 가져와 기본적으로 팩토리와 정확히 동일한 방식으로 수행하는 방식으로 작성할 수 있습니다. 즉, 팩토리로 서비스를 작성하여 객체를 반환 할 수 있습니다.

대부분의 사람들이 서비스보다는 공장을 사용하는 것을 권장하는 이유는 무엇입니까? 이것은 Pawel Kozlowski의 저서 : AngularJS를 사용한 웹 응용 프로그램 개발 마스터 링에서 얻은 최고의 답변입니다.

팩토리 메소드는 오브젝트를 AngularJS 종속성 주입 시스템으로 가져 오는 가장 일반적인 방법입니다. 매우 유연하고 정교한 생성 로직을 포함 할 수 있습니다. 팩토리는 정규 함수이므로 "사설"변수를 시뮬레이션하기 위해 새로운 어휘 범위를 활용할 수도 있습니다. 이는 특정 서비스의 구현 세부 사항을 숨길 수 있으므로 매우 유용합니다. "


1
  • 공장 당신은 실제로 만들 객체 의 내부 공장을 하고 돌아갑니다.
  • 으로 서비스 당신은 단지가 표준 기능 용도 this함수를 정의하는 키워드를.
  • 제공 거기의 $get당신이 정의하고 사용할 수 있습니다 얻기 위해 데이터를 반환하는 개체를.

1

(: AngularJS와 비즈니스 로직을 처리하는 세 가지 방법이 있습니다 물론 Yaakov의 코 세라 AngularJS와에서 영감 있습니다) :

  1. 서비스
  2. 공장
  3. 공급자

여기서는 Service vs Factory 에 대해서만 이야기하겠습니다.

서비스 :

통사론:

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>

서비스의 주요 기능 :

  1. 지연 인스턴스화 : 서비스가 주입되지 않으면 인스턴스화되지 않습니다. 따라서 그것을 사용하려면 모듈에 주입해야합니다.

  2. Singleton : 여러 모듈에 주입되면 모든 특정 인스턴스에만 액세스 할 수 있습니다. 그렇기 때문에 여러 컨트롤러간에 데이터를 공유하는 것이 매우 편리합니다.

공장

이제 AngularJS의 팩토리에 대해 이야기 해 봅시다.

먼저 문법을 보자 :

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

이제 컨트롤러에서 위의 두 가지를 사용하십시오.

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

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

공장 특징 :

  1. 이러한 유형의 서비스는 공장 설계 패턴을 따릅니다 . 팩토리는 새로운 객체 나 메소드를 생성하는 중심 장소로 생각할 수 있습니다.

  2. 이는 싱글 톤뿐만 아니라 맞춤형 서비스도 제공합니다.

  3. .service()방법은 단일 유형 인 동일한 유형의 서비스를 항상 생성 하는 팩토리 입니다. 동작을 구성하는 쉬운 방법은 없습니다. 이 .service()방법은 일반적으로 구성이 필요없는 항목의 바로 가기로 사용됩니다.



0

이 비유로 차이점을 이해할 수 있습니다. 일부 값을 반환하는 일반 함수와 새 키워드를 사용하여 인스턴스화되는 생성자 함수의 차이점을 고려하십시오. 따라서 팩토리를 만드는 것은 일부 값을 반환하는 일반 함수를 만드는 것과 비슷합니다 (기본 또는 서비스를 만드는 것은 새로운 키워드를 사용하여 인스턴스를 만들 수있는 생성자 함수 (OO 클래스)를 만드는 것과 같습니다. 여기서 주목할 것은 Service 메소드를 사용하여 서비스를 작성할 때 AngularJS가 지원하는 의존성 주입 메커니즘을 사용하여 인스턴스를 자동으로 작성한다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.