如何避免类似 类 和类似方法的重复?

How to avoid duplication on similar classes and similar methods?

上下文

我正在与非常相似的 class 一起工作,例如 RechargeResponseConsultResponse。所有这些(大约 80 个)都是从具有相同结构的 WSDL 方案生成的。 (此方案来自3PP公司,无法更改此逻辑。)

它们每个都包含内部 classes:RechargeResultConsultResult

我有一堆功能相同的方法。唯一的区别是我需要调用(例如)response.get_ClassName_Result().getAny() 来检查数据。

问题

我怎样才能避免在每个方法中使用相同的代码,只更改 ClassNameMethod?


是否可以使用泛型、反射或其他解决方案? (我认为像字符串一样解析 classname 不是解决方案)。

下面的代码示例:

类似classes:

    public class ConsultResponse {
        protected ConsultResult consultResult;
    
        public ConsultResult getConsultResult() {
            return consultResult;
        }
    
        public static class ConsultResult {
            protected Object any;
            public Object getAny() {
                return any;
            }
            public void setAny(Object value) {
                this.any = value;
            }
    
        }
    }

   public class RechargeResponse {
        protected RechargeResult rechargeResult;
    
        public RechargeResult getRechargeResult() {
            return rechargeResult;
        }
    
        public static class RechargeResult {
            protected Object any;
            public Object getAny() {
                return any;
            }
            public void setAny(Object value) {
                this.any = value;
            }
    
        }
    }

每个class的相似(重复)方法:

    private void validateConsult(ConsultResponse response) {
        if (response == null ||
        response.getConsultResult() == null ||              // need solution here
        response.getConsultResult().getAny() == null) {     // need solution or change here
        throw new Exception();
        }
    }

有几种解决方法,例如创建一个 superclass,ConsultResponseRechargeResponse 将从中扩展。 superclass 将定义共享方法,因此您不必在扩展 classes 中定义它,除非您想覆盖它。

另一种方法是将验证完全分离到单独的 class 中,例如 ResponseValidator 将自行处理验证并将包含在 [=10] 中并使用=] 和 RechargeResponse classes.

很难确定一个确切的解决方案,因为这取决于您的具体情况,我们并不完全了解。

其中一个问题是您的 get«classname»Result 方法名称包含 class 名称。这使得不使用反射就不可能使其通用。为什么不将两者都重命名为 getResult?然后,您可以使用泛型来使 class 成为泛型。

  1. 首先,我们定义一个接口,它同时定义了getAnysetAny

    public interface Result {
        Object getAny();
        void setAny(Object value);
    }
    
  2. 然后我们可以创建 Result 的实现,例如 ConsultResult。你可以用 RechargeResult.

    做同样的事情
    public class ConsultResult implements Result {
        protected Object any; // You already have a getter, so this can also be private
    
        public Object getAny() {
            return this.any;
        }
    
        public void setAny(Object value) {
            this.any = value;
        }
    }
    
  3. 然后我们可以创建一个基础classResponse,它定义了getResult方法。 class 接受类型参数 T 必须实现 Result.

    public abstract class Response<T extends Result> {
    
        protected T result; // You already have a getter, so this can also be private
    
        public T getResult() {
            return this.result;
        }
    }
    
  4. 最后,我们也创建了我们的ConsultResponseclass。我们从 Response 扩展它,并提供类型参数 ConsultResult.

    public class ConsultResponse extends Response<ConsultResult> {
        // The field 'result' is already present within the Response class,
        // so there is no need to include it here.
    }
    

此外,正如 GhostCat 已经在评论中所说:首先拥有两个不同的内部 classes 有什么意义?它们在您的示例中与当前编写的相同。您可以将它们替换为单个碱基 class;但是,可能是那些 classes 中有更多成员未在您的示例中显示,因此我将它们保留在我的示例中。


对于验证,您可以执行大致相同的操作。