请耐心听我说。我知道还有其他答案,比如: AngularJS:服务vs提供商vs工厂

然而,我仍然不知道你什么时候会使用服务而不是工厂。

据我所知,factory通常用于创建可以被多个控制器调用的“通用”函数:创建通用控制器函数

比起服务,Angular文档似乎更喜欢工厂。他们甚至在使用工厂时提到“服务”,这更令人困惑!http://docs.angularjs.org/guide/dev_guide.services.creating_services

那么什么时候使用服务呢?

是否有一些事情只有通过服务才能做到或更容易做到?

幕后有什么不同吗?性能/内存差异呢?

举个例子。除了声明的方法,它们看起来是一样的,我不明白为什么我要做一个而不是另一个。http://jsfiddle.net/uEpkE/

更新:从Thomas的回答中,似乎暗示服务是为了更简单的逻辑,而工厂是为了更复杂的逻辑和私有方法,所以我更新了下面的小提琴代码,似乎两者都能支持私有函数?

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

当前回答

工厂和服务都产生了单例对象,这些对象可以由提供者配置,并注入到控制器和运行块中。从被注入者的角度来看,对象来自工厂还是来自服务绝对没有区别。

那么,什么时候使用工厂,什么时候使用服务?这可以归结为您的编码偏好,而不是其他。如果你喜欢模块化JS模式,那就选择工厂模式。如果你喜欢构造函数(“类”)风格,那么就选择服务。注意,这两种样式都支持私有成员。

从面向对象的角度来看,该服务的优势可能是它更直观:创建一个“类”,并与提供者一起跨模块重用相同的代码,并通过在配置块中向构造函数提供不同的参数来改变实例化对象的行为。

其他回答

所有这些提供者的概念都比最初看起来要简单得多。如果你仔细分析一个提供程序,把它的不同部分拿出来,就会非常清楚。

简单地说,这些提供者中的每一个都是另一个的专门版本,顺序是:提供者>工厂>值/常量/服务。

只要提供程序做了你能做的,你就可以在链的更下方使用它,这将导致编写更少的代码。如果它不能完成你想要的,你可以继续往上走,你只需要写更多的代码。

这张图说明了我的意思,在这张图中,你将看到一个提供者的代码,突出显示的部分显示了提供者的哪些部分可以用来创建工厂、值等。

(来源:simplygoodcode.com)

要了解更多细节和例子,请访问:http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

服务

语法:模块。service('serviceName',函数); 结果:当将serviceName声明为可注入参数时,你将得到传递给module.service的实际函数引用。

使用方法:可以通过简单地将()附加到注入的函数引用来共享有用的实用程序函数。也可以用injectedArg运行。调用(这个)或类似的方法。

工厂

语法:模块。factory('factoryName',函数);

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

用法:可能用于返回一个'class'函数,然后可以重新创建实例。

供应商

语法:模块。provider('providerName',函数);

结果:当将providerName声明为一个可注入参数时,您将获得通过调用传递给module.provider的函数引用的$get方法返回的值。

用途:可能用于返回一个'类'函数,然后可以重新创建实例,但在注入之前需要某种配置。也许对跨项目可重用的类有用?我还是不太清楚。

可以使用你想要的方式:是否创建对象或只是从两者访问函数


您可以从服务中创建新对象

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

注意:

服务默认返回对象而不是构造函数。 这就是构造函数函数被设为这个的原因。模型属性。 由于此服务将返回对象,但是但是对象内部将是用于创建新对象的构造函数;

您可以从工厂创建新对象

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默认返回构造函数函数而不是对象。 这就是为什么new object可以用构造函数function创建。

创建只访问简单功能的服务

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

结论:

您可以使用您想要的方式,无论是创建新对象或 只是为了访问简单的函数 使用其中一种而不是另一种,不会对性能造成任何影响 两者都是单例对象,每个应用程序只创建一个实例。 在每个传递引用的地方都只有一个实例。 在angular文档中,工厂被称为服务,服务也被称为服务。

与服务相比,没有什么是工厂做不到或做得更好的。反之亦然。工厂似乎更受欢迎。这样做的原因是方便处理私人/公共成员。在这方面,服务将更加笨拙。 在编码Service时,你倾向于通过“this”关键字将对象成员设为public,然后可能突然发现那些public成员对于私有方法(即内部函数)是不可见的。

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'

Angular使用" new "关键字为你创建一个服务,所以Angular传递给控制器的实例也会有同样的缺点。 当然你可以用this/that来解决这个问题:

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'  

但是对于一个大的服务常量this\that-ing会使代码可读性很差。 此外,服务原型不会有private成员,只有public成员可以使用:

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'

综上所述,使用Factory更加方便。As Factory没有这些缺点。我建议在默认情况下使用它。

工厂和服务是最常用的方法。它们之间唯一的区别是,Service方法更好地用于需要继承层次结构的对象,而Factory可以生成JavaScript原语和函数。

Provider函数是核心方法,其他的都是语法糖。只有在构建需要全局配置的可重用代码段时才需要它。

创建服务有五种方法:Value、Factory、Service、Provider和Constant。你可以在这里了解更多关于angular service的信息,这篇文章用实际的演示例子解释了所有这些方法。

.