English 中文(简体)
使用“操作”的操作者是否考虑过“设计”?
原标题:Is This Use of the "instanceof" Operator Considered Bad Design?

在我的一个项目中,我有两个“数据传输物体”记录Type1和记录Type2, 继承一个抽象的记录类别。

I want both RecordType objects to be processed by the same RecordProcessor class within a "process" method. My first thought was to create a generic process method that delegates to two specific process methods as follows:

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
}

I ve 读到Scott Meyers在Effective C++上写道:

"Anytime you find yourself writing code of the form if the object is of type T1, then do something, but if it s of type T2, then do something else, slap yourself."

如果他正确的话,我显然应该 myself笑自己。 我看不出这种设计是坏的(当然,除非有人在记录Type3中填加,而没有在处理这种设计的通用“程序”方法中增加另一行,从而形成一种NPE),而且我认为,其他办法可以涉及将具体处理逻辑的首当其冲放在记录Type班上,而记录Type课程本身对我来说确实没有什么意义,因为从理论上讲,我喜欢在这些记录上进行的各种处理。

某人能否解释为什么可能认为这种设计不好,并提供某种替代方法,仍然把处理这些记录的责任交给“处理”类别?

<><>UPDATE:

  • Changed return null to throw new IllegalArgumentException(record);
  • Just to clarify, there are three reasons a simple RecordType.process() method would not suffice: First, the processing is really too far removed from RecordType to deserve its own method in the RecordType subclasses. Also, there are a whole slew of different types of processing that could theoretically be performed by different processors. Finally, RecordType is designed to be a simple DTO class with minimal state-changing methods defined within.
最佳回答

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

Usage (note the generic return type):

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。

问题回答

我的建议:

public RecordType process(RecordType record){
    return record.process();
}

public class RecordType
{
    public RecordType process()
    {
        return null;
    }
}

public class RecordType1 extends RecordType
{
    @Override
    public RecordType process()
    {
        ...
    }
}

public class RecordType2 extends RecordType
{
    @Override
    public RecordType process()
    {
        ...
    }
}

如果需要执行守则与模式的线索(如情报和安全局)相结合,那么你将需要使用一种双重派遣或访问模式。

http://en.wikipedia.org/wiki/Double_dispad

另一种可能的做法是使程序(或者说,如果程序澄清了事情的话)成为抽象的(记录表格),并在次类别中实际执行。 e.g.

class RecordType {
   protected abstract RecordType doSubclassProcess(RecordType rt);

   public process(RecordType rt) {
     // you can do any prelim or common processing here
     // ...

     // now do subclass specific stuff...
     return doSubclassProcess(rt);
   }
}

class RecordType1 extends RecordType {
   protected RecordType1 doSubclassProcess(RecordType RT) {
      // need a cast, but you are pretty sure it is safe here
      RecordType1 rt1 = (RecordType1) rt;
      // now do what you want to rt
      return rt1;
   }
}

Watch out for a couple of typos - think I fixed them all.

设计是一种结束的手段,不了解您的目标或制约因素,任何人都无法说明你的设计是否适合这一特定情况,或如何加以改进。

然而,在目标设计中,在单独类别中保持方法执行的标准做法是visitor patterns

PS:在一项法律审查中,I dcode>return no,因为它可能传播而不是报告。 考虑:

RecordType processed = process(new RecordType3());

// many hours later, in a different part of the program

processed.getX(); // "Why is this null sometimes??"

理论上说,所谓的不可击退的法典道路应当成为一种例外,而不是导致不明确的行为。

一种设想中的错误设计,例如,在适用的情况下不使用visitor模式。

另一种是eff>,instanceof,与其他技术相比相当缓慢,例如对照“{>>>,使用平等。

在使用<visitor模式时,通常使用<代码>Map绘制<>>>>支持代码><>/代码>和Visitor的地图。 http://www.un.org/spanish/ecosoc 检查非常无效。

这违反了开放式的开放式国际投资争端解决中心的原则。





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签