工厂模式和ngResource

时间:2015-12-16 16:59:39

标签: angularjs angularjs-factory angularjs-resource

我有一个工厂,提供对资源对象的访问,如下所示。最初,我在控制器内部实现了这个功能,但是将其移到工厂中,使其在整个应用程序中更具可重用性。

当我构建它时,供应商角度文档中的一行引起了我的注意:

  

最佳实践:将工厂函数命名为Factory(例如,apiTokenFactory)。虽然不需要这种命名约定,但在导航代码库或查看调试器中的堆栈跟踪时会有所帮助。 (source

我显然没有在下面这样做(因为我跟随resource Doc的模式)。但后来我试图找出哪种提供者符合条件,而且我不确定,并且他们不会为任何其他类型的提供商提供最佳实践说明。我应该使用service()代替factory()吗? (我无法找到明确的答案。)

这个问题显然有很低的风险,因为应用程序工作正常(比我没有使用工厂时更好)。但我对意见充满好奇。

...

.factory("Entries",Entries)

...

function Entries($resource,config) {
    endpoint = config.endpoint + ":" + config.port + "/entry";
    return $resource(endpoint + '/:id', {id:'@id'},
        { 'get':    {method:'GET'},
          'create': {method:'POST'},
          'update': {method:'PUT'},
          'query':  {method:'GET', isArray:true},
          'remove': {method:'DELETE'},
          'delete': {method:'DELETE'}
        }
    );
}

1 个答案:

答案 0 :(得分:1)

如果它作为工厂工作,请将其作为工厂保存。我从不使用服务提供商,因为我发现它不提供工厂方法的任何东西,并且我的大脑更容易掌握工厂模式。

对于工厂,您提供的函数返回您想要角度注入器使用的对象。使用服务,您可以提供构造函数。然后,注入器通过使用提供的功能新建对象来创建将被注入的对象。 Angular工厂和服务部门总是单身,但是提供一个Constructor函数来创建一个单独的对象在我看来有点像矫枉过正。

在您的情况下,如果您将其转换为服务,您的对象基本上只是作为代理,如下所示

...

.service("Entries",Entries)

...

function Entries($resource,config) {
    var endpoint = config.endpoint + ":" + config.port + "/entry";
    var resource = $resource(endpoint + '/:id', {id:'@id'},
        { 'get':    {method:'GET'},
          'create': {method:'POST'},
          'update': {method:'PUT'},
          'query':  {method:'GET', isArray:true},
          'remove': {method:'DELETE'},
          'delete': {method:'DELETE'}
        }
    );

    this.get = resource.get;
    this.create = resource.create;
    this.update = resource.update;
    this.query = resource.query;
    this.remove = resource.remove;
    this.delete = resource.delete;
}

这非常难看并且没有任何用处,除非你真的想要抽象出你正在使用$资源,你可以再次使用工厂来轻松

...

.factory("Entries",Entries)

...

function Entries($resource,config) {
    var endpoint = config.endpoint + ":" + config.port + "/entry";
    var resource = $resource(endpoint + '/:id', {id:'@id'},
        { 'get':    {method:'GET'},
          'create': {method:'POST'},
          'update': {method:'PUT'},
          'query':  {method:'GET', isArray:true},
          'remove': {method:'DELETE'},
          'delete': {method:'DELETE'}
        }
    );

    return {
        get: resource.get,
        create: resource.create,
        update: resource.update,
        query: resource.query,
        remove: resource.remove,
        delete: resource.delete
    }
}

即使是角度文档似乎也无法提供使用服务的令人信服的理由。他们为服务最合适时提供的示例是(取自here

鉴于您有一个现有的构造函数

function UnicornLauncher(apiToken) {

  this.launchedCount = 0;
  this.launch = function() {
    // Make a request to the remote API and include the apiToken
    ...
    this.launchedCount++;
  }
}

工厂提供商看起来像

myApp.factory('unicornLauncher', ["apiToken", function(apiToken) {
  return new UnicornLauncher(apiToken);
}]);

使用服务时,您可以将其设为oneliner

myApp.service('unicornLauncher', ["apiToken", UnicornLauncher]);

对我来说并不太令人兴奋,当然也不是一个很好的理由让我经历思考,无论这应该是服务还是工厂。我的建议是忘记service()存在并只使用工厂