【问题标题】:Factory pattern with parameterized methods带有参数化方法的工厂模式
【发布时间】:2020-01-24 20:18:07
【问题描述】:

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

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

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
    }
}

问题如下。 95% 的服务将遵循这种模式。但是,一小部分需要客户端请求才能将后端响应转换为客户端响应。

所以方法:

public abstract T4 transformBackendResponseToClientResponse(T3 backendResponse);

会变成:

public abstract T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse);

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

如何在不重复代码的情况下实现?

【问题讨论】:

    标签: java code-duplication factory-method


    【解决方案1】:

    一个选项可能是在大约 5% 的场景中使用额外的接口。该接口可能如下所示,您的具体类将定义为extends CommonService implements LessCommonInterface

    interface LessCommonInterface<T1, T3, T4> {
        T4 transformBackendResponseToClientResponse(T1 clientRequest, T3 backendResponse);
    }
    

    另一种选择是创建第二个抽象类来扩展第一个抽象类。这样,约 95% 的具体类将定义为 extends CommonService,而约 5% 的具体类将定义为 extends LessCommonService

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

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

    【讨论】:

      【解决方案2】:

      如果您使用的是 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);
          }
          }
      

      2。将您的抽象类标记为实现接口。 95% 将使用默认实现,其他将使用覆盖版本。希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多