根据我的理解,当我在工厂中返回一个被注入到控制器的对象。当在服务中,我使用这个处理对象,不返回任何东西。

我假设服务总是单例的,并且每个控制器中都会注入一个新的工厂对象。然而,正如事实证明的那样,工厂对象也是单例的吗?

演示的示例代码:

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

更改用户时。首先在ACtrl中,结果是那个用户。BCtrl中的first也改变了,例如User is a singleton?

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


当前回答

在AngularJS中有三种处理业务逻辑的方法:(灵感来自Yaakov的Coursera AngularJS课程):

服务 工厂 提供者

这里我们只讨论服务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>

服务的主要特点:

惰性实例化:如果服务没有被注入,它将永远不会被实例化。所以要使用它,你必须将它注入到一个模块中。 单例:如果它被注入到多个模块中,所有模块都只能访问一个特定的实例。这就是为什么在不同的控制器之间共享数据是非常方便的。

工厂

现在让我们来谈谈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();

工厂特点:

这种类型的服务遵循工厂设计模式。工厂可以被认为是创建新对象或方法的中心场所。 这不仅可以生成单例服务,还可以生成可定制的服务。 .service()方法是一个工厂,它总是生成相同类型的服务,即单例服务。没有简单的方法来配置它的行为。.service()方法通常用作不需要任何配置的快捷方式。

其他回答

有关简短的解释,请参阅https://stackoverflow.com/a/26924234/5811973。

详细解释请参考https://stackoverflow.com/a/15666049/5811973。

同样来自angularJs文档:

补充第一个答案,我认为.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);
    }]);
  }

对于工厂,你实际上是在工厂内部创建一个对象并返回它。 对于该服务,您只有一个使用this关键字进行定义的标准函数 函数。 在提供程序中,你定义了一个$get,它可以用来获取返回的对象 数据。

服务样式:(可能是最简单的一种)返回实际函数:用于共享实用程序函数,只需将()附加到注入的函数引用即可调用。

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

});

提供者样式:(完整的、可配置的版本)返回函数的$get函数的输出:可配置。

AngularJS中的Providers是你能创建的最灵活的工厂形式。向模块注册提供者就像向服务或工厂注册一样,只是使用了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();
    }

});

斯库尔克·延科夫

<!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>

斯菲德尔

所有提供者都以相同的方式工作。不同的方法服务、工厂、提供者只是让你用更少的代码完成同样的事情。

附注:还有价值和常数。

从提供者开始到价值结束的链条上的每个特殊情况都有一个附加的限制。所以要在两者之间做出选择,你必须问问自己,哪一个能让你用更少的代码完成你想要的。

下面这张图可以说明我的意思:

你可以在我的博客文章中找到这张照片的分类和参考指南:

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