让我们说我有一个AngularJS数据服务,该服务调用服务器并返回一个可以使用其他方法扩展的对象。例如,假设以下函数是NerdDinner之类的AngularJS服务的一部分。
function getDinner(dinnerId) {
return $http.get('api/dinner/' + dinnerId)
.then(loadDinnerComplete)
.catch(loadDinnerFailed);
function loadDinnerComplete(response) {
return new Dinner(response.data);
}
}
一个地方定义晚餐课的最佳做法是什么?这是一个单独的文件工厂吗?我在NerdDinner服务中定义了吗?或者我在GetDinner类中定义它(假设这是唯一可以创建晚餐的方法)?
我没有找到任何关于在style guide中创建对象的具体参考,所以请原谅我,如果它被覆盖并且我错过了它。
修改 我最终决定接受Jeroen's answer,因为它最符合我对一个相当简单的用例的需求。但是,Daniel's answer是纯金,不应该被忽视。如果我选择使用简单的CRUD或其他基于服务器的操作来扩展DTO的功能,那么$ resource是一种很好的方法。
答案 0 :(得分:7)
在John Papa的风格指南(afaik)中没有明确提到商业实体(如晚餐)的位置。
如果你想走这条路(使用商业实体并在那里放置逻辑),我应该为每个实体提供自己的工厂:
(function() {
'use strict';
angular
.module('myDinner')
.factory('Dinner', DinnerFactory);
function DinnerFactory() {
Dinner.prototype.eat = eat;
Dinner.prototype.cancel = cancel;
return Dinner;
// Constructor
function Dinner (data) {
// this is just an example:
this.time = data.time;
this.location = data.location;
}
// Methods
function eat() {
// ...
}
function cancel() {
// ...
}
}
})();
然后您可以使用Dinner
将它们注入您的控制器或其他服务对象,并使用Dinner
创建一个新的new Dinner(data)
对象。
您也可以使用服务,但John Papa不鼓励服务,因为它们与工厂太相似。
答案 1 :(得分:4)
国际海事组织你正在做的事情已经在$resource
完成了。你在谈论"定义数据对象" (或者,典型用语中的模型)。也就是说,定义每个"数据对象"正如John Papa关于单一问题的建议一样,它自己的工厂就是这样做的。
John Papa在factories section.
中谈到了这一点如果你想手工完成这项工作,IMO你可以定义你的模型并在每个模型上附加代表各种crud操作的方法。这是模式$resource
和restangular(有点)。
//Dinner model as angular factory, each of these methods returns a promise
function Dinner($http) {
return {
create: function(route, body) { /** http.post */ },
get: function(route) { /** http.get */ },
update: function(route, body) { /** http.put */ },
destroy: function(route) { /** http.delete */ }
};
}
现在您的Dinner
模型内置了方便的crud方法,因此您可以执行
var dinner = new Dinner;
dinner.get("/api/dinner/1").then() //get dinner with id of 1
dinner.update("/api/dinner/1", {name: "burger"}).then() //update dinner with id of 1
编辑:
因此,如果您想创建一个与检索数据无关的对象,您应该创建另一个需要您的模型的工厂。这将您的数据检索与数据操作分离。在OP原始示例中,数据检索和操作紧密耦合。
function Meal(dinner) {
//this.meal is the specified dinner
this.meal = new Dinner().get("/api/dinner" + dinner);
//some random build-in data manipulation methods
return {
getCalories: function() { return this.meal * 400; },
getPrice: function() { return (this.meal * 100) + "$"; }
};
}
现在您已将数据操作分离为单独的对象,您可以执行此类操作(但这是同步示例)
var mcdonalds = new Meal(/** specify which dinner */)
mcdonalds.getPrice() //$4.56
mcdonalds.getCalores() //9999
答案 2 :(得分:2)
我个人使用Services
和Factories
来创建对象。然而,来自John Papa的风格指南:
使用
new
关键字对服务进行实例化,对公共方法和变量使用this
。由于这些与工厂非常相似,因此请使用工厂以保持一致性。
在SRP之后,您应该将其放在新的Service
或Factory
中,而不是另一个 app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
});
。