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

我希望两个RecordType对象在“process”方法中由相同的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/

    10-09 09:49