我设计了一个定义GetJsonRequset和POstJsonRequest的抽象类。
我的抽象类与方法签名一起定义如下:
public abstract class RequestBuilder
{
protected object GetJsonRequest(string connectionUriString, string queryString, Func<string,object> parseDelegate )
protected object PostJsonRequest(string connectionUriString, string queryString, string inputBody, Func<string,object> parseDelegate )
....
}
现在所有子类都按如下方式传入委托。
public class ProjectListBuilder : RequestBuilder
{
public ProjectContext Build()
{
this.AddRequestHeader("TokenKey", this.authenticationModel.TokenKey);
if(!string.IsNullOrEmpty(this.page))
{
this.AddRequestHeader("Page", this.page);
}
string connectionstring = String.Concat(this.authenticationModel.ServiceBaseUrl, projectURI);
List<ProjectModel> projectModels = (List<ProjectModel>)GetJsonRequest(connectionstring, string.Empty, Parse);
return new ProjectContext(this.authenticationModel, this.page, projectModels);
}
/// <summary>
/// delegate used to parse resonse from server. Converts Json from server to strongly type object.
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public List<ProjectModel> Parse(string json)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<ProjectModel>));
using(MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
return (List<ProjectModel>)serializer.ReadObject(stream);
}
}
}
这适用于第一次通过,但它有一种奇怪的气味。我如何重新考虑这一点以满足更加SOLID的设计?
答案 0 :(得分:2)
您的ProjectListBuilder
实际负责构建请求吗?或者它是否也通过代表(SRP)解析响应?您可能希望将该委托注入。
我不清楚Build
方法名称。似乎它也会发出请求,但如果是这种情况,则该名称具有误导性。
GetJsonRequest
和PostJsonRequest
返回什么?我希望可以发送到服务器的请求对象,但我不知道,因为返回类型是object
。另外object
是一件令人讨厌的事情,因为它会占用CPU时间来装箱和拆箱。使用接口(接口分离原则),例如:
interface Request
{
public Response send();
}
或者更好:使用泛型:
interface Request<TResponse>
{
public TResponse send();
}
你也可以在这里注入代表:
interface Request<TResponse>
{
public TResponse send(Func<string, TResponse> responseParser);
}
我还会选择特定的构建器并使用嵌套类:
public abstract class BaseRequest<TResponse> : Request<TResponse>
{
// ...
}
public class GetJsonRequest<TResponse> : BaseRequest<TResponse>
{
public class Builder
{
// ...
public GetJsonRequest<TResponse> Build()
{
// ...
return new GetJsonRequest<TResponse>(uri, page);
}
}
// ...
public TResponse send(Func<string, TResponse> responseParser)
{
// ...
}
}
所以我可以这样使用它:
var builder = new GetJsonRequest<Project>.Builder();
builder.setPage(page);
builder.setUri(uri);
GetJsonRequest<Project> request = builder.Build();
Project myProject = request.send(json => ParseProjectJson(json))
很干净。