Java:在构造函数或方法中传递参数?

时间:2011-07-19 10:57:00

标签: java constructor

目前我有一个类TransactionData,它只比POJO多一点。我从HTTPServletRequest构建对象。我做了什么:

public class TransactionData
{

    // ...

    public TransactionData(HttpServletRequest request) throws IOException
    {
        // do actual work here
    }

}

这里有很多WTF,最令人不安的是对象TransactionDataHTTPServletRequest紧密耦合。我的想法:使用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。

编辑:问题甚至可能是我的预感完全错误,我可以毫不后悔地解雇它

5 个答案:

答案 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一起使用的包装器,我认为应该没问题。

相关问题