AngularJS:什么时候用service代替factory

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

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

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

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

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

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

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

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

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

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()
];
}
125351 次浏览

解释

这里有不同的东西:

第一:

    如果你使用一个服务,你将得到函数的实例 ("this" 关键字)。李< / >
  • 如果你使用工厂,你将得到返回的值 调用函数引用 (factory中的return语句)

裁判: 角。Service vs angular.factory

第二:

记住,AngularJS中的所有提供者(value, constant, services, factories)都是单例的!

第三:

使用一个或另一个(服务或工厂)是关于代码风格的。 但是,AngularJS中的常见的方式将使用工厂。< / p >

为什么?

因为 工厂方法是将对象导入AngularJS依赖注入系统的最常用方法。它非常灵活,可以包含复杂的创建逻辑。由于工厂是常规函数,我们还可以利用新的词法作用域来模拟“私有”变量。这非常有用,因为我们可以隐藏给定服务的实现细节。”

(裁判: http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821)。


使用

通过简单地将()附加到注入的函数引用中,可以用于共享对调用有用的实用函数。也可以用injectedArg.call(this)或类似的方法运行。

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

所以,当您有复杂的逻辑时使用工厂在你的服务和您不希望暴露这种复杂性

在其他情况下如果你想返回一个服务的实例,只需使用service

但是随着时间的推移你会发现80%的情况下你会用到工厂。

更多详细信息:http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


更新:

这里的精彩帖子: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html < / p >

"如果你想要函数像普通函数一样调用,使用 工厂< em > < / em >。如果你想要你的函数用new 接线员,使用服务。如果您不知道其中的区别,请使用factory。" < / p >


更新:

AngularJS团队做了他的工作,并给出了一个解释: http://docs.angularjs.org/guide/providers < / p >

从这一页开始:

“工厂和服务是最常用的食谱。它们之间唯一的区别是Service recipe更好地用于自定义类型的对象,而Factory可以生成JavaScript原语和函数。”

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

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

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

allernhwkim最初在这个问题上发布了一个答案链接到他的博客,但版主删除了它。这是我发现的唯一一篇文章,它不仅告诉你如何用服务、提供者和工厂做同样的事情,而且还告诉你用提供者可以做什么而用工厂不能做什么,用工厂不能做什么。

直接来自他的博客:

app.service('CarService', function() {
this.dealer="Bad";
this.numCylinder = 4;
});


app.factory('CarFactory', function() {
return function(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
};
});


app.provider('CarProvider', function() {
this.dealerName = 'Bad';
this.$get = function() {
return function(numCylinder) {
this.numCylinder = numCylinder;
this.dealer = this.dealerName;
}
};
this.setDealerName = function(str) {
this.dealerName = str;
}
});

这表明CarService总是生产4汽缸的汽车,你不能为单个汽车更改它。而CarFactory返回一个函数,因此你可以在你的控制器中执行new CarFactory,传递一些特定于该车的气缸。你不能做new CarService,因为CarService是一个对象而不是一个函数。

工厂不这样运作的原因是:

app.factory('CarFactory', function(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
});

并自动返回一个函数让你实例化,是因为你不能这样做(添加东西到原型/等):

app.factory('CarFactory', function() {
function Car(numCylinder) {
this.dealer="Bad";
this.numCylinder = numCylinder
};
Car.prototype.breakCylinder = function() {
this.numCylinder -= 1;
};
return Car;
});

看看它是如何字面上生产汽车的工厂。

他博客的结论很好:

总之,

---------------------------------------------------
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------
| Factory | Yes      | Yes          | No          |
---------------------------------------------------
| Service | Yes      | No           | No          |
---------------------------------------------------
| Provider| Yes      | Yes          | Yes         |
---------------------------------------------------
  1. 当你只需要一个简单的对象时使用Service,例如Hash, for 这很容易编码,但是你不能实例化 李。< / p > < / >

  2. 当你需要实例化一个对象时使用Factory,即new Customer(), new Comment(),等等

  3. 需要配置时使用Provider。即测试url, QA url, 李生产url。< / p > < / >

如果你发现你只是在工厂中返回一个对象,你可能应该使用service。

不要这样做:

app.factory('CarFactory', function() {
return {
numCylinder: 4
};
});

改用service:

app.service('CarService', function() {
this.numCylinder = 4;
});

服务

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

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

工厂

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

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

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

供应商

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

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

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

与服务相比,没有什么是工厂做不到或做得更好的。反之亦然。工厂似乎更受欢迎。这样做的原因是方便处理私人/公共成员。在这方面,服务将更加笨拙。 在编码Service时,你倾向于通过“this”关键字将对象成员设为public,然后可能突然发现那些public成员对于私有方法(即内部函数)是不可见的。< / p >
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会使代码可读性很差。 此外,服务原型不会看到私有成员-只有公共成员对他们可用:

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没有这些缺点。我建议在默认情况下使用它。

即使他们说所有的服务和工厂都是单例的,我也不完全同意。我想说的是,工厂不是单身的,这就是我回答的重点。我真的会考虑定义每个组件的名称(服务/工厂),我的意思是:

工厂因为不是单例对象,所以在注入时可以创建任意数量的对象,因此它的工作方式类似于对象工厂。您可以创建域实体的工厂,并更轻松地使用这些对象,这些对象可以像您的模型对象一样。当你检索几个对象时,你可以将它们映射到这个对象中,它可以充当DDBB和AngularJs模型之间的另一层。你可以给对象添加方法这样你的AngularJs App就更面向对象了。

与此同时,服务是一个单例对象,所以我们只能创建一个,也许不能创建,但当我们注入一个控制器时,我们只有一个实例,所以服务提供更像一个公共服务(rest调用,功能..)到控制器。

从概念上讲,可以像服务提供服务一样,工厂可以创建一个类的多个实例(对象)

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

简单地说,这些提供程序中的每一个都是另一个的专门版本,顺序如下:provider > factory > value / constant / service

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

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

< p > AngularJS providers, factories, services etc are all the same thing < br > (来源:simplygoodcode.com) < /订阅>

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

可以同时使用你想要的方式:无论是创建对象还是j访问功能


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

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方法更好地用于需要继承层次结构的对象,而Factory可以生成JavaScript原语和函数。

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

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