代码库中满是这样的代码:

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);

07-24 16:06