对服务与工厂感到困惑

时间:2012-12-07 11:31:55

标签: angularjs

据我了解,当在工厂内部时,我返回一个被注入控制器的对象。在服务内部时,我使用this处理对象而不返回任何内容。

我假设服务总是单身,并且每个控制器都会注入新工厂对象。然而,事实证明,工厂对象也是单身?

示例代码:

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.first中的ACtrl时,user.first中的BCtrl也发生了变化,例如User是单身人士?

我的假设是在一个带工厂的控制器中注入了一个新实例?

22 个答案:

答案 0 :(得分:598)

所有角度服务都是单身

文档(请参阅服务作为单身人士):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

答案 1 :(得分:379)

对我来说,当我意识到他们都以同样的方式工作时,我会发现这一点:通过运行一次,存储他们获得的价值,然后咳出相同的存储价值通过依赖注入引用时。

说我们有:

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

三者之间的区别在于:

  1. a的存储值来自于运行fn,换句话说:fn()
  2. b的储值来自new fn,换句话说:new fn()
  3. c的存储值来自首先通过new fn获取实例,然后运行实例的$get方法
  4. 这意味着,有一些类似于角度内的缓存对象,每次注入的值只分配一次,当它们第一次注入时,其中:

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

    这就是我们在服务中使用this并在提供商中定义this.$get的原因。

    希望这有帮助。

答案 2 :(得分:96)

live example

“你好世界”的例子

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

答案 3 :(得分: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

这里是谷歌小组的网页,在那里进行了讨论:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

答案 4 :(得分:51)

以下是主要区别:

服务

语法:module.service( 'serviceName', function );

结果:当将serviceName声明为可注入参数时,将向您提供传递给module.service函数实例

用法:对于共享实用程序函数非常有用,只需将()附加到注入的函数引用即可调用。也可以使用injectedArg.call( this )或类似方式运行。

工厂

语法:module.factory( 'factoryName', function );

结果:当将factoryName声明为注入参数时,将提供通过调用传递给module.factory的函数引用返回的值。

用法:可用于返回'class'函数,然后可以将其设置为创建实例。

同时在stackoverflow AngularJS documentation上检查confused about service vs factory和类似问题。

这是example using services and factory。详细了解AngularJS service vs factory

答案 5 :(得分:27)

添加第一个答案,我认为.service()适用于以更面向对象的方式编写代码的人(C#/ Java)(使用此关键字并通过prototype / Constructor函数实例化对象)。

Factory适用于编写代码的开发人员,这些代码对于javascript /函数式编码更为自然。

看看angular.js里面的.service和.factory方法的源代码 - 在内部它们都调用了provider方法:

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

答案 6 :(得分:25)

非常简单:

.service - 注册函数将作为构造函数调用(又名' newed')

.factory - 注册函数将作为一个简单函数调用

两次都被调用,导致单个对象被注入到应用程序的其他组件中。

答案 7 :(得分:20)

所有提供商的工作方式相同。不同的方法servicefactoryprovider只是让您在更少的代码中完成同样的事情。

P.S。还有valueconstant

provider开始,以value开头的链中的每个特殊情况都有一个额外的限制。因此,要在它们之间做出决定,你必须问自己哪些能让你用更少的代码完成你想要的东西。

这张图片向您展示了我的意思:

enter image description here

您可以在我从以下网站获得此图片的博文中提供细分和参考指南:

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

答案 8 :(得分: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

答案 9 :(得分:13)

“工厂”和“服务”是以角度进行DI(依赖注入)的不同方式。

因此,当我们使用“服务”定义DI时,如下面的代码所示。这将创建一个新的“Logger”对象的GLOBAL实例,并将其注入函数。

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

使用“工厂”定义DI时,它不会创建实例。它只是传递方法,后来消费者在内部必须为工厂调用对象实例。

app.factory("Customerfactory", CreateCustomer);

下面是一个简单的图像,直观地显示了“服务”的DI流程与“工厂”的不同。

enter image description here

当我们想要根据场景创建不同类型的对象时,应该使用工厂。例如,取决于我们想要创建简单“客户”对象的场景,或者具有“地址”对象的“客户”或具有“电话”对象的“客户”。 Here is a detailed explanation of this paragraph

当我们有像实用程序,记录器,错误处理程序等一样注入实用程序或共享函数时,应该使用服务。

答案 10 :(得分: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中实例化一个像新Object()的对象。

Factory是一个创造价值的功能。当服务,控制器等需要从工厂注入的值时,工厂按需创建值。一旦创建,该值将重用于需要注入的所有服务,控制器等。

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

});

提供程序样式:(完整版,可配置版)返回函数$ 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

答案 11 :(得分:2)

基本区别在于, provider 允许将原始(非对象),数组或回调函数值设置为工厂声明的变量,因此如果返回一个对象,则必须明确宣布并返回。

另一方面, service 只能用于将服务声明变量设置为对象,因此我们可以避免显式创建和返回对象,而另一方面它允许使用关键字。

或简而言之,“提供商是一种更通用的形式,而服务仅限于对象”。

答案 12 :(得分:2)

这就是我在设计模式方面理解它们之间的区别:

服务:返回一个类型,该类型将被新建以创建该类型的对象。如果使用Java类比,则Service返回 Java类定义

工厂:返回可以立即使用的具体对象。在Java类比中,工厂返回 Java对象

经常使人(包括我自己)感到困惑的部分是,当您在代码中注入服务或工厂时,它们可以以相同的方式使用,在两种情况下您在代码中获得的内容都是您可以使用的具体对象立即调用。这意味着在服务的情况下,角度代表您在服务声明上调用“新”。我认为这是一个令人费解的概念。

答案 13 :(得分:2)

AngularJS Service vs Factory

module.service( 'serviceName', function );

module.factory( 'factoryName', function );

serviceName声明为injectable参数时,您将获得该函数的实例。换句话说,新FunctionYouPassedToService()。如果需要,此对象实例将成为AngularJS注册并稍后注入其他services / controllers的服务对象。

factoryName声明为injectable参数时,将通过调用传递给module.factory的函数引用来提供返回的值。

在下面的示例中,我们以两种不同的方式定义MyService。请注意.service中如何使用this.methodname创建服务方法。在.factory中,我们创建了一个工厂对象并为其分配了方法。

AngularJS .service

module.service('MyService', function() {
    this.method1 = function() {
            //..
        }

    this.method2 = function() {
            //..
        }
});

AngularJS .factory

module.factory('MyService', function() {

    var factory = {}; 

    factory.method1 = function() {
            //..
        }

    factory.method2 = function() {
            //..
        }

    return factory;
});

答案 14 :(得分:2)

我们可以定义这样的服务:

app.service('MyService', function () {
   this.sayHello = function () {
      console.log('hello');
   };
});

.service()是我们模块上的一个方法,它采用名称和定义服务的函数。挺直的。一旦定义,我们就可以在其他组件中注入和使用该特定服务,例如控制器,指令和过滤器,如下所示:

现在和工厂一样:

app.factory('MyService', function () {
    return {
       sayHello: function () {
           console.log('hello');
       }
    }
});

同样,.factory()是我们模块上的一个方法,它还有一个名称和一个定义工厂的函数。我们可以完全按照与服务相同的方式注入和使用该东西。现在有什么区别?

好吧,你可能会看到,而不是在工厂中使用它,我们返回一个对象文字。这是为什么?事实证明,服务是构造函数,而工厂不是。在这个Angular世界的深处,有这个代码在实例化时使用服务构造函数调用Object.create()。但是,工厂函数实际上只是一个被调用的函数,这就是我们必须明确返回一个对象的原因。

答案 15 :(得分:1)

这将是了解Service Vs Factory Vs Provider

的最佳和简短的答案

来源https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J

所说的演示 http://jsbin.com/ohamub/1/edit?html,output

“代码中有评论说明了主要区别,但我会在这里稍微扩展一下。作为一个说明,我只是想了解这一点,所以如果我说出任何错误,请告诉我。” / p>

<强> 服务

语法:module.service('serviceName',function);

结果:将serviceName声明为injectable参数时,将提供传递给module.service的实际函数引用。

用法:通过简单地向注入的函数引用附加()来共享对调用有用的实用程序函数非常有用。也可以使用injectArg.call(this)或类似的方式运行。

<强> 工厂

语法:module.factory('factoryName',function);

结果:将factoryName声明为injectable参数时,将通过调用传递给module.factory的函数引用来提供返回的值。

用法:对于返回一个“类”函数非常有用,该函数可以随后用于创建实例。

<强> 提供商

语法:module.provider('providerName',function);

结果:当将providerName声明为injectable参数时,将通过调用传递给module.provider的函数引用的$ get方法来提供返回的值。

用法:对于返回一个“类”函数非常有用,该函数可以随后用于创建实例,但在注入之前需要某种配置。对于可跨项目重用的类可能有用吗?这个还是有点朦胧。“ 本

答案 16 :(得分:1)

我有一段时间的困惑,我正在努力在这里提供一个简单的解释。希望这会有所帮助!

angular .factoryangular .service都用于初始化服务并以相同的方式工作。

唯一的区别是,您希望如何初始化服务。

两者都是单身人士

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

<小时/>

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

如果您想从具有返回值的功能初始化您的服务,则必须使用此factory方法。

e.g。

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

app.factory('myService', myService);

注入此服务时(例如,向您的控制器):

  • Angular将调用您的给定函数(作为myService())以返回对象
  • Singleton - 只调用一次,存储并传递相同的对象。

<小时/>

服务

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

如果您想从构造函数(使用this关键字)初始化您的服务,则必须使用此service方法。

e.g。

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

app.service('myService', myService);

注入此服务时(例如,向您的控制器):

  • Angular将new您的给定函数(作为new myService())返回对象
  • Singleton - 只调用一次,存储并传递相同的对象。

<小时/> 注意:如果您将factory<constructor function>service<function with a return value>一起使用,则无法使用。

示例 - DEMOs

答案 17 :(得分: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()函数的Angular源代码片段:

 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掌握Web应用程序开发。

  

工厂方法是获取对象的最常用方法   AngularJS依赖注入系统。它非常灵活,可以   包含复杂的创建逻辑。由于工厂是正规的   功能,我们也可以利用新的词法范围   模拟“私人”变量。这非常有用,因为我们可以隐藏   给定服务的实现细节。“

答案 18 :(得分:1)

  • 使用工厂,您实际上会在工厂内创建对象并将其返回。
  • 使用服务,您只需使用{strong>标准功能,即可使用 this关键字定义 功能
  • 使用提供商,您定义了$get,可以使用来获取返回的对象 数据。

答案 19 :(得分:1)

在AngularJS中有三种处理业务逻辑的方法:(受Yaakov&Coursera AngularJS课程的启发):

  1. 服务
  2. 提供商
  3. 这里我们只讨论服务 vs 工厂

    <强>服务

    语法:

    <强> 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. Lazily Instantiated :如果没有注入服务,它就不会被实例化。因此,要使用它,您必须将其注入模块。

    2. Singleton :如果将它注入多个模块,则所有模块都只能访问一个特定实例。这就是为什么在不同控制器之间共享数据非常方便。

    3. <强> FACTORY

      现在让我们谈谈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()方法通常用作不需要任何配置的快捷方式。

答案 20 :(得分:1)

简短说明请参考https://stackoverflow.com/a/26924234/5811973

有关详细说明,请参阅https://stackoverflow.com/a/15666049/5811973

还来自angularJs文档: enter image description here

答案 21 :(得分:0)

你可以理解这个类比的区别 - 考虑一个将返回一些值的普通函数和将使用new keyword实例化的构造函数之间的区别。所以创建工厂就像创建普通函数一样,它将返回一些值(原始或对象)而创建服务就像创建构造函数(OO类),我们可以使用new关键字创建实例。唯一需要注意的是,当我们使用Service方法创建服务时,它将使用AngularJS支持的依赖注入机制自动创建它的实例