如何避免类似 类 和类似方法的重复?
How to avoid duplication on similar classes and similar methods?
上下文
我正在与非常相似的 class 一起工作,例如 RechargeResponse
或 ConsultResponse
。所有这些(大约 80 个)都是从具有相同结构的 WSDL 方案生成的。 (此方案来自3PP公司,无法更改此逻辑。)
它们每个都包含内部 classes:RechargeResult
和 ConsultResult
。
我有一堆功能相同的方法。唯一的区别是我需要调用(例如)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,ConsultResponse
和 RechargeResponse
将从中扩展。 superclass 将定义共享方法,因此您不必在扩展 classes 中定义它,除非您想覆盖它。
另一种方法是将验证完全分离到单独的 class 中,例如 ResponseValidator
将自行处理验证并将包含在 [=10] 中并使用=] 和 RechargeResponse
classes.
很难确定一个确切的解决方案,因为这取决于您的具体情况,我们并不完全了解。
其中一个问题是您的 get«classname»Result
方法名称包含 class 名称。这使得不使用反射就不可能使其通用。为什么不将两者都重命名为 getResult
?然后,您可以使用泛型来使 class 成为泛型。
首先,我们定义一个接口,它同时定义了getAny
和setAny
。
public interface Result {
Object getAny();
void setAny(Object value);
}
然后我们可以创建 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;
}
}
然后我们可以创建一个基础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;
}
}
最后,我们也创建了我们的ConsultResponse
class。我们从 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 中有更多成员未在您的示例中显示,因此我将它们保留在我的示例中。
对于验证,您可以执行大致相同的操作。
上下文
我正在与非常相似的 class 一起工作,例如 RechargeResponse
或 ConsultResponse
。所有这些(大约 80 个)都是从具有相同结构的 WSDL 方案生成的。 (此方案来自3PP公司,无法更改此逻辑。)
它们每个都包含内部 classes:RechargeResult
和 ConsultResult
。
我有一堆功能相同的方法。唯一的区别是我需要调用(例如)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,ConsultResponse
和 RechargeResponse
将从中扩展。 superclass 将定义共享方法,因此您不必在扩展 classes 中定义它,除非您想覆盖它。
另一种方法是将验证完全分离到单独的 class 中,例如 ResponseValidator
将自行处理验证并将包含在 [=10] 中并使用=] 和 RechargeResponse
classes.
很难确定一个确切的解决方案,因为这取决于您的具体情况,我们并不完全了解。
其中一个问题是您的 get«classname»Result
方法名称包含 class 名称。这使得不使用反射就不可能使其通用。为什么不将两者都重命名为 getResult
?然后,您可以使用泛型来使 class 成为泛型。
首先,我们定义一个接口,它同时定义了
getAny
和setAny
。public interface Result { Object getAny(); void setAny(Object value); }
然后我们可以创建
做同样的事情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; } }
然后我们可以创建一个基础class
Response
,它定义了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; } }
最后,我们也创建了我们的
ConsultResponse
class。我们从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 中有更多成员未在您的示例中显示,因此我将它们保留在我的示例中。
对于验证,您可以执行大致相同的操作。