2014-01-13 43 views
4

我看角的通用工廠CRUD(這我目前在超過使用服務的偏好):在Angular中重複使用相同的數據工廠是否可行?

app.factory('dataFactory', ['$http', function ($http) { 
    var urlBase = '/odata/ContentTypes'; 

    // The _object_ defined in the factory is returned to the caller, rather than as with a service, 
    // where the _function_ defined in the service is returned to the caller 
    var dataFactory = {}; 

    dataFactory.getContentTypes = function() { 
     var contentTypes = $http.get(urlBase); 

     return contentTypes; 
    }; 

    dataFactory.getContentType = function (id) { 
     return $http.get(urlBase + '/' + id); 
    }; 

    dataFactory.insertContentType = function (contentType) { 
     return $http.post(urlBase, contentType); 
    }; 

    dataFactory.updateContentType = function (contentType) { 
     return $http.put(urlBase + '/' + contentType.ID, contentType); 
    } 

    dataFactory.deleteContentType = function (id) { 
     return $http.delete(urlBase + '/' + id); 
    } 


    // to traverse navigation properties 
    //dataFactory.getUserFromContentTypeId = function (id) { 
    // return $http.get(urlBase + '/' + id + '/user'); 
    //} 


    //dataFactory.getOrders = function (id) { 
    // return $http.get(urlBase + '/' + id + '/orders'); 
    //}; 


    return dataFactory; 

}]); 

我所有的實體,這些代碼將是大致相同的。是否有可能注入實體名稱(或相應的RESTful路徑),如果是這樣,可以像分部類一樣處理,如果需要額外的承諾(例如遍歷導航屬性),它們也可以注入?

如果這可能與Angular有關,有人可以發表一些例子嗎?

回答

11

個人而言,我喜歡讓我的代碼DRY我發現,如果你保持一個共同的約定對您的服務器API,你可以走很長的路,不管你怎麼稱呼它一個基地工廠/倉庫/類或。我在AngularJs中實現這一點的方式是使用一個返回基礎知識庫類的AngularJs工廠,即工廠返回一個帶有原型定義而不是對象實例的JavaScript類函數,我把它稱爲abstractRepository。然後,對於每個資源,我爲該特定資源創建了一個具體資源庫,從abstractRepository原型繼承,因此我從abstractRepository繼承了所有共享/基本功能,併爲具體資源庫定義了任何資源特定功能。

我認爲一個例子會更清晰。讓我們假設你的服務器API使用以下網址約定(我不是一個REST最純粹的,所以我們不約定了任何你想要實現的):

GET -> /{resource}?listQueryString  // Return resource list 
GET -> /{resource}/{id}    // Return single resource 
GET -> /{resource}/{id}/{resource}view // Return display representation of resource 
PUT -> /{resource}/{id}    // Update existing resource 
POST -> /{resource}/     // Create new resource 
etc. 

我個人使用Restangular所以下面的例子是基於它的,但是您應該能夠輕鬆地將其適用於$http$resource

abstractRepository

app.factory('abstractRepository', [function() { 

    function abstractRepository(restangular, route) { 
     this.restangular = restangular; 
     this.route = route; 
    } 

    abstractRepository.prototype = { 
     getList: function (params) { 
      return this.restangular.all(this.route).getList(params); 
     }, 
     get: function (id) { 
      return this.restangular.one(this.route, id).get(); 
     }, 
     getView: function (id) { 
      return this.restangular.one(this.route, id).one(this.route + 'view').get(); 
     }, 
     update: function (updatedResource) { 
      return updatedResource.put(); 
     }, 
     create: function (newResource) { 
      return this.restangular.all(this.route).post(newResource); 
     } 
     // etc. 
    }; 

    abstractRepository.extend = function (repository) { 
     repository.prototype = Object.create(abstractRepository.prototype); 
     repository.prototype.constructor = repository; 
    }; 

    return abstractRepository; 
}]); 

混凝土倉庫,讓我們使用客戶爲例:

app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) { 

    function customerRepository() { 
     abstractRepository.call(this, restangular, 'customers'); 
    } 

    abstractRepository.extend(customerRepository); 
    return new customerRepository(); 
}]); 

然後在你的控制器,你注入customerRepository

app.controller('CustomerController', ['$scope', 'customerRepository', function($scope, customerRepository) { 
    // Use your customerRepository 
}]); 

什麼你」會發現如果你使用這個基礎知識庫模式是因爲你的大多數CRUD控制器也會共享很多的通用代碼,所以我通常創建一個基本的CRUD控制器,我的控制器繼承自使用$injector.invoke,但我會留下這樣的例子,因爲它是超出了這個問題的範圍。

+0

好東西。我做了'$ http'的簡單重構,我稍後可能會改變......小步驟。我將OData URL Base放在具體的存儲庫中,而不是在控制器中。當然有用,但是想知道是否推薦? – ElHaix

+0

我真的很喜歡這種方法! – beeman

+0

不錯,我在找它! – Sajgoniarz

相關問題