代码库中满是这样的代码:
BaseRecord record = // some BaseRecord
switch(record.source()) {
case FOO:
return process((FooRecord)record);
case BAR:
return process((BarRecord)record);
case QUUX:
return process((QuuxRecord)record);
.
. // ~25 more cases
.
}
接着
private SomeClass process(BarRecord record) { }
private SomeClass process(FooRecord record) { }
private SomeClass process(QuuxRecord record) { }
这让我非常难过。然后,每次从
BaseRecord
派生一个新类时,我们都必须遍历我们的代码库,以更新这些case语句并添加新的process
方法。这种逻辑在各处重复出现,我认为太多了,无法为每个逻辑添加方法并在类中覆盖。我该如何改善? 最佳答案
第一个解决方案:良好的旧多态性。
只需在BaseRecord类中添加一个抽象的process()
方法,并在每个子类中覆盖它即可。该代码将因此变为:
BaseRecord record = ...;
record.process();
如果您不能将
process()
方法添加到BaseRecord类(及其子类)中,请实施visitor pattern。它将把处理方法留在BaseRecord类之外,但是每次添加新的子类时,都将被迫修改Visitor接口及其所有实现。因此,编译器将为您检查您是否忘记了开关中的大小写。public interface RecordVisitor<T> {
T visitFoo(FooRecord foo);
T visitBar(BarRecord foo);
...
}
public abstract class BaseRecord {
public abstract <T> T accept(RecordVisitor<T> visitor);
}
public class FooRecord extends BaseRecord {
@Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitFoo(this);
}
}
public class BarRecord extends BaseRecord {
@Override
public <T> T accept(RecordVisitor<T> visitor) {
return visitor.visitBar(this);
}
}
现在,您只需为问题中描述的每个逻辑块实现RecordVisitor:
RecordVisitor<Void> visitor = new ProcessRecordVisitor();
record.accept(visitor);