首页 文章

对服务与工厂感到困惑

提问于
浏览
602

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

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

用于演示的示例代码:

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 中更改 user.first 时,事实证明 BCtrl 中的 user.first 也发生了变化,例如 User 是单身?

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

22 回答

  • 51

    All angular services are singletons

    文档(请参阅单项服务):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 + "!";
        }
      }
    });
    

    看看这个关于$ offer的演示文稿:http://slides.wesalvaro.com/20121113/#/

    这些幻灯片用于AngularJs的一次聚会:http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html

  • 2

    对我来说,当我意识到它们都以相同的方式工作时,就会产生这样的启示:通过运行某些东西 once ,存储它们获得的值,然后在通过依赖注入引用时咳嗽 that same stored value .

    说我们有:

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

    三者之间的区别在于:

    • a 的存储值来自运行 fn ,换句话说: fn()

    • b 的储值来自 new ing fn ,换句话说: new fn()

    • c 的存储值来自首先通过 new ing fn 获取实例,然后运行实例的 $get 方法

    这意味着,有一些类似于角度内的缓存对象,每次注入的值只分配一次,当它们第一次注入时,其中:

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

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

    希望这可以帮助 .

  • 2

    这将是了解Service Vs Factory Vs Provider的最佳和简短的答案

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

    这是什么 bendemo http://jsbin.com/ohamub/1/edit?html,output

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

    Services

    Syntax :module.service('serviceName',function);

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

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

    Factories

    Syntax :module.factory('factoryName',function);

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

    Usage :可以用于返回'class'函数,然后可以新建这个函数来创建实例 .

    Providers

    Syntax :module.provider('providerName',function);

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

    Usage :可以用于返回一个'class'函数,然后可以将其创建为创建实例,但在注入之前需要某种配置 . 对于可跨项目重用的类可能有用吗?这个还是有些朦胧 . “本

  • 1

    实例

    “你好世界”的例子

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

    还有一种方法可以返回构造函数,这样就可以在工厂中返回 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

  • 8

    以下是主要差异:

    服务

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

    结果:将serviceName声明为可注入参数时,将向您提供传递给 module.serviceinstance of a function .

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

    工厂

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

    结果:将factoryName声明为可注入参数时,将提供传递给 module.factoryvalue that is returned by invoking the function reference .

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

    还要检查AngularJS documentation和stackoverflow confused about service vs factory上的类似问题 .

    这是example using services and factory . 了解更多关于AngularJS service vs factory的信息 .

  • 93

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

    工厂适用于编写代码的开发人员,这些代码对于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);
        }]);
      }
    
  • 25

    非常简单:

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

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

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

  • 2

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

    附:还有 valueconstant .

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

    这是一张图片,向您展示我的意思:

    enter image description here

    您可以在博客文章中找到细分和参考指南,我从以下网址获得此图片:

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

  • 1

    以下是服务与工厂的更多示例,这些示例可能有助于了解它们之间的差异 . 基本上,一个服务有“new ...”调用它,它已经被实例化了 . 工厂不会自动实例化 .

    基本示例

    返回具有单个方法的类对象

    这是一个具有单一方法的服务:

    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
    
  • 27

    “工厂”和“服务”是角度进行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

    应该使用服务当我们有实用程序或共享函数被注入时,如Utility,Logger,Error handler等 .

  • 1

    Service style :(可能是最简单的)返回实际函数:用于共享实用函数,通过简单地将()附加到注入的函数引用来调用它 .

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

    Factory style :(更多涉及但更复杂)返回函数的返回值:在java中实例化一个对象,如new Object() .

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

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

    Provider style :(完整版,可配置版)返回函数$ 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}}
        	

    {{factoryOutput}}

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

  • 2

    基本区别在于提供程序允许将原始(非对象),数组或回调函数值设置为工厂声明的变量,因此如果返回一个对象,则必须显式声明并返回它 .

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

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

  • 1

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

    Service :返回一个类型,该类型将被新建以创建该类型的对象 . 如果使用Java类比,则Service返回 Java Class definition .

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

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

  • 1

    AngularJS服务与工厂

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

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

    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() . 但是,工厂函数实际上只是一个被调用的函数,这就是我们必须显式返回一个对象的原因 .

  • 57

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

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

    The only difference is, how you want to initialize your service.

    Both are Singletons


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

    工厂

    app.factory(<服务名称>,<带返回值的函数>)

    如果您想从 a function that you have with a return value 初始化您的服务,则必须使用此 factory 方法 .

    例如

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

    When injecting this service (e.g. to your controller):

    • Angular将 call 您的给定函数(作为 myService() )返回该对象

    • Singleton - 仅调用一次,存储并传递相同的对象 .


    服务

    app.service(<服务名称>,<构造函数>)

    如果您想从 a constructor function (使用 this 关键字)初始化您的服务,则必须使用此 service 方法 .

    例如

    function myService() {
      this.myfunc: function (param) { /* do stuff */ }
    }
    
    app.service('myService', myService);
    

    When injecting this service (e.g. to your controller):

    • Angular会 new 你的给定函数(如 new myService() )返回对象

    • Singleton - 仅调用一次,存储并传递相同的对象 .


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


    示例 - DEMO

    • Angular Service vs Factory

    • Angular Service vs Factory (with route)

  • 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依赖注入系统的最常用方法 . 它非常灵活,可以包含复杂的创建逻辑 . 由于工厂是常规功能,我们还可以利用新的词法范围来模拟“私有”变量 . 这非常有用,因为我们可以隐藏给定服务的实现细节 . “

  • 371
    • 使用 factory ,您实际上在 factory 内创建 object 并将其返回 .

    • 使用 service ,您只需要 standard function ,它使用 this 关键字来定义函数 .

    • 使用 provider ,您定义了 $get ,可以使用 to get 返回数据的对象 .

  • 20

    在AngularJS中有三种处理业务逻辑的方法:( Inspired by Yaakov's Coursera AngularJS course ),它们是:

    • 服务

    • 工厂

    • 提供者

    在这里我们只谈谈 Service vs Factory

    SERVICE

    句法:

    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>
    

    服务的主要特点:

    • Lazily Instantiated:如果没有注入服务,它将不会被实例化 . 因此,要使用它,您必须将其注入模块 .

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

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

    工厂特点:

    • 此类服务遵循 factory design pattern . 可以将工厂视为创建新对象或方法的中心位置 .

    • 这不仅可以生成单例,还可以生成可自定义的服务 .

    • .service() 方法是 factory ,它始终生成相同类型的服务,即单例 . 没有简单的方法来配置它的行为 . .service() 方法通常用作不需要任何配置的快捷方式 .

  • 13

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

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

    也来自angularJs文档:
    enter image description here

  • 13

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

相关问题