目前我有一个类TransactionData
,它只比POJO多一点。我从HTTPServletRequest
构建对象。我做了什么:
public class TransactionData
{
// ...
public TransactionData(HttpServletRequest request) throws IOException
{
// do actual work here
}
}
这里有很多WTF,最令人不安的是对象TransactionData
与HTTPServletRequest
紧密耦合。我的想法:使用TransactionDataExtractor
方法创建一个接口extract()
,以便我可以实现不同的类来构建对象。
public interface TransactionDataExtractor
{
public TransactionData extract();
}
但是如何将构建TransactionData所需的东西传递给每个实现?想到的第一件事是使用不同的构造函数,如下所示:
public class TransactionDataExtractorRequest implements TransactionDataExtractor
{
private HttpServletRequest httpRequest;
public TransactionDataExtractorRequest(HttpServletRequest httpRequest)
{
this.httpRequest = httpRequest;
}
public TransactionData extract()
{
// do whatever is required
}
}
但是在这种情况下,每当我需要构建一个新的TransactionData对象时,我必须创建一个新的TransactionDataExtractorRequest。我完全不喜欢隐含的依赖。
我能想到的另一个选择是将Object参数传递给extract()
并在需要时抛出它,放弃类型安全并引入大量锅炉板丑陋代码
public TransactionData extract(Object o)
{
HttpServletRequest h;
if (o instanceof HttpServletRequest)
{
h = (HttpServletRequest)o;
}
//...
}
我不知道自己是否已经说清楚了。我觉得我错过了一些东西,我知道解决方案非常简单,但我无法掌握它。 有什么想法吗? TIA。
编辑:问题甚至可能是我的预感完全错误,我可以毫不后悔地解雇它
答案 0 :(得分:4)
如果您将源对象传递给extract()
时唯一的问题是确保类型安全,则可以使用泛型:
public interface TransactionDataExtractor<E> {
public TransactionData extract(E source);
}
public class TransactionDataExtractorRequest
implements TransactionDataExtractor<HttpServletRequest> {
public TransactionData extract(HttpServletRequest source) { ... }
}
答案 1 :(得分:3)
我觉得我错过了什么......有什么想法吗?
我的想法是你试图解决一个不是真正问题的问题。没有明显的(对我而言)为什么你试图摆脱的耦合实际上是有害的。当然,您尝试删除耦合并不会使代码更容易理解。
答案 2 :(得分:3)
如果您仅依赖请求参数,则可以获取request.getParameterMap()
并使用Map
代替。 (如果您需要标题 - getHeaders()
)
答案 3 :(得分:1)
创建/重用TransactionDataExtractorRequest
实例不是问题,恕我直言。无论如何你需要在某个地方区分参数类型,如果你通过使用某种工厂来解耦TransactionData和参数类型,那有什么问题呢?
答案 4 :(得分:1)
我仍然不相信通过消除对HttpServletRequest
的依赖来获得更多,但我建议采取以下措施:
public class TransactionData {
public TransactionData(TransactionDataOptions options) throws IOException {
// do actual work here
}
}
//TransactionData wants some state that it currently gets from a HttpServletRequest,
//figure out what that state is, and abstract an interface for accessing it
public interface TransactionDataOptions {
//getters for things that TransactionData needs
}
//take all the code that pulls state out of the HttpServletRequest, and move it here
public class TransactionDataHttpOptions implements TransactionDataOptions {
private HttpServletRequest request;
//getter implementations that pull the required information out of the request
public TransactionDataHttpOptions(HttpServletRequest request) {
this.request = request;
}
}
//now you can also do this, and use TransactionData even without a HttpServletRequest
public class TransactionDataMapOptions implements TransactionDataOptions {
private Map<String, Object> map;
//getter implementations that pull the required information out of the map
public TransactionDataHttpOptions(Map<String, Object> map) {
this.map = map;
}
}
如果你走这条路线,那么TransactionDataHttpOptions
是唯一依赖HttpServletRequest
的对象。因为它基本上是一个旨在与HttpServletRequest
一起使用的包装器,我认为应该没问题。