gpt4 book ai didi

java - "instanceof"运算符的这种使用是否被认为是糟糕的设计?

转载 作者:IT老高 更新时间:2023-10-28 21:12:52 26 4
gpt4 key购买 nike

在我的一个项目中,我有两个“数据传输对象”RecordType1 和 RecordType2,它们继承自 RecordType 的抽象类。

我希望两个 RecordType 对象都由“进程”方法中的同一 RecordProcessor 类处理。我的第一个想法是创建一个通用的流程方法,它委托(delegate)给两个特定的流程方法,如下所示:

public RecordType process(RecordType record){

if (record instanceof RecordType1)
return process((RecordType1) record);
else if (record instanceof RecordType2)
return process((RecordType2) record);

throw new IllegalArgumentException(record);
}

public RecordType1 process(RecordType1 record){
// Specific processing for Record Type 1
}

public RecordType2 process(RecordType2 record){
// Specific processing for Record Type 2
}

我读到 Scott Meyers 在 Effective C++ 中写了以下内容:

“任何时候你发现自己在写这样的代码‘如果对象是 T1 类型,那么做某事,如果它是 T2 类型,那么做其他事情,’打自己一巴掌。”

如果他是正确的,显然我应该扇自己耳光。我真的不明白这是多么糟糕的设计(当然,除非有人继承 RecordType 并添加 RecordType3 而不向处理它的通用“Process”方法添加另一行,从而创建 NPE),以及我能想到的替代方案涉及将特定处理逻辑首当其冲地放在 RecordType 类本身中,这对我来说真的没有多大意义,因为理论上我可以对这些记录执行许多不同类型的处理。

有人可以解释为什么这可能被认为是糟糕的设计,并提供某种替代方案,仍然将处理这些记录的责任交给“处理”类吗?

更新:

  • return null改为throw new IllegalArgumentException(record);
  • 澄清一下,一个简单的 RecordType.process() 方法不够用的原因有以下三个:首先,处理与 RecordType 相去甚远,不值得在 RecordType 子类中使用自己的方法。此外,理论上可以由不同的处理器执行大量不同类型的处理。最后,RecordType 被设计成一个简单的 DTO 类,其中定义了最少的状态更改方法。

最佳答案

Visitor在这种情况下通常使用模式。虽然代码有点复杂,但在添加一个新的 RecordType 子类后,您必须在任何地方实现逻辑,否则将无法编译。 instanceof 到处都是,很容易漏掉一两个地方。

例子:

public abstract class RecordType {
public abstract <T> T accept(RecordTypeVisitor<T> visitor);
}

public interface RecordTypeVisitor<T> {
T visitOne(RecordType1 recordType);
T visitTwo(RecordType2 recordType);
}

public class RecordType1 extends RecordType {
public <T> T accept(RecordTypeVisitor<T> visitor) {
return visitor.visitOne(this);
}
}

public class RecordType2 extends RecordType {
public <T> T accept(RecordTypeVisitor<T> visitor) {
return visitor.visitTwo(this);
}
}

用法(注意泛型返回类型):

String result = record.accept(new RecordTypeVisitor<String>() {

String visitOne(RecordType1 recordType) {
//processing of RecordType1
return "Jeden";
}

String visitTwo(RecordType2 recordType) {
//processing of RecordType2
return "Dwa";
}

});

另外我建议抛出异常:

throw new IllegalArgumentException(record);

当没有找到任何类型时,而不是返回 null

关于java - "instanceof"运算符的这种使用是否被认为是糟糕的设计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8841577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com