当前位置: 首页 > 面试题库 >

使用“ instanceof”运算符是否被认为是不良设计?

东门阳飇
2023-03-14
问题内容

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

我希望两个RecordType对象在“
process”方法中由相同的RecordProcessor类处理。我的第一个想法是创建一个通用的处理方法,该方法将两个特定的处理方法委托给以下人员:

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 nullthrow new IllegalArgumentException(record);
  • 为了澄清起见,有一个简单的RecordType.process()方法不能满足以下三个原因:首先,处理实际上离RecordType太远了,不能在RecordType子类中保留其自己的方法。同样,理论上可以由不同的处理器执行一系列不同类型的处理。最后,RecordType被设计为具有最少状态更改方法的简单DTO类。

问题答案:

该访问者模式通常在这样的情况下使用。尽管代码有些复杂,但是添加新的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找不到这两种类型时返回。



 类似资料:
  • 问题内容: 我们正在将两个系统集成到一个Intranet中,使用CORS作为在两个域之间进行AJAX调用的一种方式。 这被认为是不良做法吗?一般认为CORS是不良做法吗? 问题答案: CORS不是坏习惯。它支持所有主要的浏览器,而且越来越多的API都支持它。实际上,如果您的公共资源不在防火墙后面,则可以将标头放在资源上是安全的。 但是,对于服务器上CORS的角色有些困惑。CORS应该仅指示特定资源

  • 问题内容: 我大致认为使用iframe是“不好的做法”。 这是真的?使用它们的优点/缺点是什么? 问题答案: 与所有技术一样,它也有起有落。如果您要使用iframe到一个经过适当开发的网站周围走走,那当然是个坏习惯。但是,有时iframe是可以接受的。 iframe的主要问题之一与书签和导航有关。如果您使用它只是将页面嵌入内容中,我认为很好。这就是iframe的用途。 但是我也看到iframe也被

  • 问题内容: 我对对象使用开关盒有疑问: 例如:我的问题可以用Java复制: 如何使用实施? 问题答案: 这是子类型多态性有帮助的典型方案。请执行下列操作 然后,你可以简单的调用上。 如果你不能随意更改,和,则可以应用访问者模式来实现相同目的。

  • 问题内容: 运算符是做什么用的?我看过类似的东西 但是,这对我来说都没有意义。我已经完成了研究,但只提出了没有任何解释的示例。 问题答案: 是用于测试对象(实例)是否为给定Type的子类型的二进制运算符。 想像: 然而,随着;, 因为是的超类型,可能较少。 和, 这是因为Dog既不是的子类型也不是的父类型Cat,并且它也不实现它。 请注意,上面用于的变量是类型。这是一个运行时操作,将我们带到一个用

  • 编译器必须为constexpr的不同路径生成多个函数,这取决于函数的调用方式。所以也许它在使用过载分辨率。 被接受的建议没有提到“sfinae”或“过载分辨率”。 所以我很好奇这两个概念是否适用于“constexpr if”。

  • 问题内容: 我正在开发一个网页,在那里我为类似国际象棋的游戏布置一块面板,以及几个棋盘托盘。所有操作都使用HTML(使用jQuery在游戏进行时进行动态更新)完成。在某个地方,我想到在页面中使用元素的绝对定位被认为是不好的做法,并且最好使用相对定位。 经过相对定位的困扰了很长时间之后,我意识到板元件的绝对定位要容易得多,而且要正确得多。 有谁知道相对定位优于绝对定位的原因吗?在决定采用哪种方法时,