我有一种情况,我正在查询以XML形式返回数据的RESTful web服务(使用.NET)。我围绕API编写了包装器函数,这样我就不会返回原始XML,而是返回反映XML结构的完整.NET对象。XML可能非常复杂,因此这些对象可能非常大且嵌套严重(例如,包含集合,而集合又可能包含其他集合等)
REST API有一个返回完整结果或基本结果的选项。基本结果返回完整结果所返回的数据的一小部分。目前,我正在处理这两种类型的响应,方法是为这两种请求返回相同的.NET对象,但在基本请求中,一些属性没有填充。这最好通过一个(非常简单化)的代码示例来展示:
public class PersonResponse
{
public string Name { get; set; }
public string Age { get; set; }
public IList<HistoryDetails> LifeHistory { get; set; }
}
public class PersonRequest
{
public PersonResponse GetBasicResponse()
{
return new PersonResponse()
{
Name = "John Doe",
Age = "50",
LifeHistory = null
};
}
public PersonResponse GetFullResponse()
{
return new PersonResponse()
{
Name = "John Doe",
Age = "50",
LifeHistory = PopulateHistoryUsingExpensiveXmlParsing()
};
}
}
正如您所看到的,PersonRequest
类有两个方法,它们都返回一个PersonResponse
对象。然而,GetBasicResponse
方法是一个"lite"版本——它不会填充所有属性(在本例中,它不会填充LifeHistory
集合,因为这是一个‘昂贵’的操作)。请注意,这是实际情况的简化版本。
然而,对我来说,这有一种明确的气味(因为GetBasicResponse
方法的调用方需要了解哪些属性不会被填充)。
我认为一种更OOP的方法是有两个PersonResponse
对象——一个BasicPersonResponse
对象和一个FullPersonResponse
对象,后者继承自前者。类似于:
public class BasicPersonResponse
{
public string Name { get; set; }
public string Age { get; set; }
}
public class FullPersonResponse : BasicPersonResponse
{
public IList<object> LifeHistory { get; set; }
}
public class PersonRequest
{
public BasicPersonResponse GetBasicResponse()
{
return new FullPersonResponse()
{
// ...
};
}
public FullPersonResponse GetFullResponse()
{
return new FullPersonResponse()
{
// ...
};
}
}
然而,这仍然不太"感觉"正确——原因我不完全确定!
有没有更好的设计模式来处理这种情况?我觉得我错过了更优雅的东西?谢谢
我认为您已经描述了代理模式。请参阅此处的详细信息:C#中的GOF设计模式示意图
对于使用继承来添加"额外数据",而不是添加/修改行为,我也有一种挥之不去的糟糕感觉。这样做的主要优点是,方法可以指定它们在参数类型中需要的详细程度。
在这个特定的例子中,我倾向于对数据传输对象(Response对象)使用第一种方法,但随后立即使用这个数据传输对象来创建数据模型对象,其确切性质在很大程度上取决于您的特定应用程序。数据传输对象应该是内部的(因为数据字段的存在或不存在是一个实现细节),公共对象或接口应该提供更适合消费代码的视图。