Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重构巨大的if(…instanceof…)_Java_Oop - Fatal编程技术网

Java 重构巨大的if(…instanceof…)

Java 重构巨大的if(…instanceof…),java,oop,Java,Oop,我目前正在尝试重构项目的一部分,如下所示: 许多班级 B extends A; C extends A; D extends C; E extends B; F extends A; ... 在代码的某个地方: if (x instanceof B){ B n = (B) x; ... }else if (x instanceof C){ C n = (C) x; ... }else if (x instanceof D){ D n = (D) x; ... }else if (

我目前正在尝试重构项目的一部分,如下所示:

许多班级

 B extends A; C extends A; D extends C; E extends B; F extends A; ...
在代码的某个地方:

if (x instanceof B){
 B n = (B) x;
 ...
}else if (x instanceof C){
 C n = (C) x;
 ...
}else if (x instanceof D){
 D n = (D) x;
 ...
}else if (x instanceof E){
 E n = (E) x;
 ...
}else if (x instanceof G){
 G n = (G) x;
 ...
}...
如果构造当前位于CC为19的函数中,请参见上文。现在我的问题是:我能把这个if构造分解成多个函数,让Java的OO发挥神奇的作用吗?还是有什么我必须注意的陷阱

我的想法是:

private void oopMagic(C obj){ ... Do the stuff from the if(x instanceof C) here}
private void oopMagic(D obj){ ... Do the stuff from the if(x instanceof D) here}
private void oopMagic(E obj){ ... Do the stuff from the if(x instanceof E) here}
....
如果:

oopMagic(x);

编辑:我无法更改任何类别(A、B、C等)。在if语句中,一些getter用于从每个对象读取(从不写入)数据。

很难说什么最有效,因为您没有给出代码正在执行的任何指示,但另一个选项是添加
oopMagic()
方法到
A
并根据需要重写。

根据这些
中的内容,
您可以在基类中创建虚拟(可能是抽象)方法
doMagic
,然后只需:

x.doMagic();

如果
部分差异很大,那么(除了在设计上有其他问题外),您可以考虑使用访问者模式实现双重分派。

这不会飞
instanceof
检测变量的运行时类型。多态性(通过签名选择方法)取决于变量的编译时类型。也就是说,您将始终获得
oopMagic(一个obj)

正如罗杰建议的那样,请看一下,也就是双重分派。

我担心(正如一位评论者所建议的那样)您只是将问题转移到其他地方,例如,if-else将在其他地方执行。你的方法没有问题,但为了让它更好,你必须做更多的工作

我的建议是创建一个映射,它将根据x的类型处理x。处理器本身是一个通用接口,类似于:

interface Processor<T extends A> {
     void oopMagic(T obj);
}
class ProcessorB<B> {
     void oopMagic(B obj) { ... }
}

如果您不能更改类的名称,您仍然可以包装它们并引入工厂为您的类型创建正确的包装器:






当然,这不会消除语句的
实例序列,但会将其移动到工厂,这至少是一个更好的地方。工厂方法几乎总是包含一些创建正确对象所需的条件检查。

原始作者是怎么想的?@darioo也许“我希望这是支持代数数据类型和模式匹配的Scala”:p@darioo,@pst:或者类似“我就这么干一次”随着时间的推移,子类不断出现。。。接下来……我相信您只是在解决问题,而不是重构它;-)@戈兰:“我会快速而肮脏地完成这一次”->你好,技术债!如果A的每个子类都必须做一些魔术,如果您能够提供默认实现,那么这是最好的解决方案。否则,您可以将您的魔法提取到一个策略中,并为所有应该是魔法的类引入一个新接口;)真的很有趣什么。。。确实如此。
map.get(x.getClass()).oopMagic(x);
public interface Wrapper {
  public void magicMethod();  // you know what I mean
}
public AWrapper implements Wrapper {
  private A a;
  public AWrapper(A a){this.a=a;};

  @Override
  public void magicMethod() {
    // do what has to be done with a
  }
}
public Factory {
  public static createWrapper(Object wrappable) {
    if (wrappable instanceof A)
        return new AWrapper((A) wrappable);
    // ...
  }
}
// ...
Object x = getXFromSomewhere();
Wrapper wrapper = Factory.getWrapper(x);
wrapper.magicMethod();
// ...