提问




  请在这里忍受我。我知道还有其他答案,例如:
  AngularJS:服务与提供商对工厂



但是,当你在工厂使用服务时,我仍然无法弄明白。


据我所知,工厂通常用于创建可由多个控制器调用的通用功能:创建通用控制器功能


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


那么何时会使用服务?


是否有可能通过服务完成或更容易完成的事情?


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


这是一个例子。除了声明的方法,它们看起来完全相同,我无法弄清楚为什么我会做一个与另一个.http://jsfiddle.net/uEpkE/[28]


更新:来自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()
    ];
}

最佳参考


说明



你有不同的东西:


第一



  • 如果您使用某项服务,您将获得功能实例(this
    关键词)。

  • 如果您使用工厂,您将获得返回的值
    调用函数引用
    (工厂中的return语句)。



ref: angular.service vs angular.factory


第二


请记住,AngularJS中的所有提供者(价值,常数,服务,工厂)都是单身人士!


第三


使用一个或另一个(服务或工厂)是关于代码风格。
但是,AngularJS中的常用方法是使用工厂


为什么?



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



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





用法



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


Factory:可以用于返回类函数,然后可以将其创建为创建实例。


因此,在您的服务中使用复杂的逻辑时使用工厂您不希望暴露这种复杂性


在其他情况下如果您想要返回服务实例,只需使用服务


但是你会随着时间的推移看到你会在我认为80%的情况下使用工厂。


有关详细信息,请访问:http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/[31]





更新:


优秀的帖子:
http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html[32]



  如果你希望你的函数像普通函数一样被调用,请使用
  的 工厂 即可。如果您希望使用new实例化您的函数
  运营商,使用服务。如果你不知道差异,请使用工厂。






更新:


AngularJS团队完成了他的工作并给出了解释:
http://docs.angularjs.org/guide/providers[33]


从这个页面:



  工厂和服务是最常用的配方。它们之间的唯一区别是服务配方更适合自定义类型的对象,而Factory可以生成JavaScript原语和功能。


其它参考1


allernhwkim最初在链接到他博客的问题上发布了一个答案,但主持人将其删除了。这是我发现的唯一一个不仅告诉你如何与服务,提供商和工厂做同样事情的帖子,而且还告诉你如何与一家工厂提供的服务,和工厂,你不能提供服务。 [36]


直接来自他的博客:


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. 当您只需要一个简单的对象(例如Hash)时使用服务
      示例{foo; 1,bar:2}编码很容易,但无法实例化
      它。

  2.   
  3. 当您需要实例化对象时使用Factory,即new
      客户(),新评论()等

  4.   
  5. 需要配置时使用提供程序。即测试网址,质量保证网址,
      生产网址。

  6.   



如果您发现只是在工厂返回一个物体,您应该使用服务。


不要这样做:


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


改为使用服务:


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

其它参考2


所有这些提供商的概念比最初出现的要简单得多。如果你剖析一个提供者并提取出不同的部分,那就很清楚了。


简而言之,这些提供者中的每一个都是另一个的专用版本,按此顺序:provider> factory> value/constant/service


只要提供商尽你所能,你就可以在链中进一步使用提供商,这将导致编写更少的代码。如果它没有达到你想要的效果,你可以上链,你只需要编写更多的代码。


这张图片说明了我的意思,在这张图片中,您将看到供应商的代码,其中突出显示的部分显示了供应商的哪些部分可用于创建工厂,价值等。


AngularJS提供商,工厂,服务等都是一样的http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider-service-factory-highlight.png [37]


有关详细信息和博客文章中的示例,请访问:http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/[38]

其它参考3


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


那么,何时使用工厂,何时使用服务?它归结为您的编码偏好,而不是其他任何东西。如果您喜欢模块化的JS模式,那就去工厂吧。如果您喜欢构造函数(class)样式,那么请转到该服务。请注意,两种样式都支持私有成员。


从OOP的角度来看,服务的优势可能是更直观:创建类,并与提供程序一起,在模块之间重用相同的代码,并简单地改变实例化对象的行为通过向配置块中的构造函数提供不同的参数。

其它参考4


与服务相比,工厂无法做到或做得更好。反之亦然。工厂似乎更受欢迎。原因是它处理私人/公共成员的便利性。在这方面,服务会更加笨拙。
在对服务进行编码时,您倾向于通过this关键字使您的对象成员公开,并且可能突然发现那些公共成员对于私有方法(即内部函数)是不可见的。


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传递给控制器​​的实例将具有相同的缺点。
当然你可以通过使用这个/那个来克服这个问题:


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'  


但是如果一个大的服务常量,这个\\会使代码难以读取。
此外,服务原型不会看到私人成员 - 只有公众可以使用:


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更方便。由于工厂没有这些缺点。我建议默认使用它。

其它参考5


即使他们说所有服务和工厂都是单身人士,我也不会100%同意。我会说工厂不是单身人士,这就是我的答案。我真的会考虑定义每个组件的名称(服务/工厂),我的意思是:


工厂因为不是单例,您可以在注入时创建任意数量的内容,因此它就像对象工厂一样工作。您可以创建域的实体工厂,并使用此对象更舒适地工作,这些对象可能类似于模型的对象。当您检索多个对象时,您可以将它们映射到此对象中,它可以作为DDBB和AngularJs模型之间的另一层。您可以向对象添加方法,以便您将对象更多地定向到AngularJs应用程序。


同时一个服务是一个单例,所以我们只能创建一个,可能不是创建,但是当我们注入一个控制器时,我们只有一个实例,所以一个服务提供更像是一个公共服务(休息电话,功能..)到控制器。


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

其它参考6


服务


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


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


工厂


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


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


用法:对于返回class函数非常有用,该函数可以是新的ed来创建实例。


提供商


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


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


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

其它参考7


可以同时使用您想要的方式:创建对象还是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();
})


注意 :



  • service默认返回object而不是构造函数。

  • 这就是构造函数设置为this.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默认返回构造函数而不是对象。

  • 这就是为什么可以使用构造函数创建新对象。




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



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


结论:



  • 您既可以使用创建新对象,也可以
    只是为了访问简单的功能

  • 使用其中一个
  • ,不会有任何性能损失
  • 两者都是单例对象,每个应用程序只创建一个实例。

  • 每个传递参考的地方只有一个实例。

  • 在角度文档工厂称为服务服务称为服务