Java 参数化方法的工厂模式

Java 参数化方法的工厂模式,java,code-duplication,factory-method,Java,Code Duplication,Factory Method,这些是一组遵循相同算法的服务。消费者调用这些服务,这些服务将消费者的请求发送到某个后端系统。服务接口是RESTful的,后端是SOAP。因为它们都遵循相同的模式,所以我们有一个抽象类。方法的顺序是固定的,即commonMethodOne需要发生在CommonMethod2之前,等等 具体类必须实现两个抽象方法,因为每个服务接口都不同 public abstract class CommonService<T1, T2, T3, T4> { public T4 getResp

这些是一组遵循相同算法的服务。消费者调用这些服务,这些服务将消费者的请求发送到某个后端系统。服务接口是RESTful的,后端是SOAP。因为它们都遵循相同的模式,所以我们有一个抽象类。方法的顺序是固定的,即commonMethodOne需要发生在CommonMethod2之前,等等

具体类必须实现两个抽象方法,因为每个服务接口都不同

public abstract class CommonService<T1, T2, T3, T4> {

    public T4 getResponse(T1 request) {
        T2 backendRequest = transformClientRequestToBackendRequest(request);
        commonMethodOne(request);
        commonMethodTwo(request);
        T3 backendResponse = getBackendResponse(backendRequest);
        commonMethodThree(backendResponse);
        commonMethodFour(backendResponse);
        return transformBackendResponseToClientResponse(backendResponse);
    }

    public abstract T2 transformClientRequestToBackendRequest(T1 request);

    public abstract T4 transformBackendResponseToClientResponse(T3 backendResponse);

    public void commonMethodOne(T1 request) {
        //some code
    }

    public void commonMethodTwo(T1 request) {
        //some code
    }

    public void commonMethodThree(T3 backendResponse) {
        //some code
    }

    public void commonMethodFour(T3 backendResponse) {
        //some code
    }

    public T3 getBackendResponse(T2 backendRequest) {
        // call to backend system
    }
}
公共抽象类CommonService{
公共T4 getResponse(T1请求){
T2后端请求=transformClientRequestToBackendRequest(请求);
公共方法一(请求);
第二条(请求);
T3 backendResponse=getBackendResponse(backendRequest);
共同方法三(后端响应);
公共方法四(后端响应);
返回TransformBackendResponse客户端响应(backendResponse);
}
公开摘要T2 transformClientRequestToBackendRequest(T1请求);
公共摘要T4 TransformBackendResponse客户响应(T3 backendResponse);
公共无效commonMethodOne(T1请求){
//一些代码
}
公共无效CommonMethod2(T1请求){
//一些代码
}
公共无效公共方法三(T3后端响应){
//一些代码
}
公共无效commonMethodFour(T3后端响应){
//一些代码
}
公共T3 getBackendResponse(T2 backendRequest){
//对后端系统的调用
}
}
问题如下。95%的服务将遵循这种模式。但是,一小部分人需要客户端请求才能将后端响应转换为客户端响应

因此,该方法:

public abstract T4 transformBackendResponseToClientResponse(T3 backendResponse)

将成为:

public abstract T4 transformBackendResponseToClientResponse(T1 clientRequest,T3 backendResponse)

然而,这只适用于服务的一小部分。因此,我不想在95%的服务中添加另一个抽象方法,也不想更改签名以保留一个方法,因为这将是对具体类的更改。另一种解决方案是拥有一个包含公共方法的父抽象类和两个子抽象类。每个类都有不同风格的
transformBackendResponseToClientResponse
,但是
getResponse
必须在每个抽象类中重复


如何在没有代码重复的情况下实现这一点?

一个选项是在~5%的情况下,在混合中使用额外的接口。该接口可以如下所示,您的具体类将被定义为
扩展CommonService implements LessCommonInterface

interface LessCommonInterface<T1, T3, T4> {
    T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse);
}
abstract class LessCommonService<T1, T2, T3, T4> extends CommonService {
    public abstract T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse);
}

另一种选择是使用一个抽象类,就像您目前所做的那样,并更改95%和5%用例的签名,以传递某种包装器对象,该包装器对象始终包含
T1
对象,有时包含
T3
对象,但这种代码很混乱,可能会随着时间的推移产生问题。

如果您使用的是Java8+,则可以使用默认方法实现。因此,一步一步地 1.从CommonService中提取接口,包括您要重写的所有方法,如

 interface ICommonService<T1, T2, T3, T4>{
       T2 transformClientRequestToBackendRequest(T1 request);
       T4 transformBackendResponseToClientResponse(T3 backendResponse);
       T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse);   
       default T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse) {
           return transformBackendResponseToClientResponse(clientRequest);
    }
    }
接口服务{
T2 transformClientRequestToBackendRequest(T1请求);
T4转换后端响应ClientResponse(T3后端响应);
T4 transformBackendResponseToClientResponse(T1 clientRequest,T3 backendResponse);
默认T4 transformBackendResponseToClientResponse(T1 clientRequest,T3 backendResponse){
返回transformBackendResponseToClientResponse(clientRequest);
}
}
二,。将抽象类标记为实现接口。95%将使用默认实现,其他将使用覆盖版本。希望能有帮助