2015-11-01 67 views
0

考虑下面的类设计:爪哇避免的instanceof通过设计

public class SuperType { }; 
public class SubType1 extends SuperType { }; 
public class SubType2 extends SuperType { }; 
public class SubType3 extends SuperType { }; 

public class Tuple { 
    SuperType t1; 
    SuperType t2; 

    public Tuple(SuperType t1, SuperType t2) { 
     this.t1 = t1; 
     this.t2 = t2; 
    } 

    public void DoSomething1() { 
     if((t1 instanceof SubType1) && (t2 instanceof SubType3)) 
      switch(t1, t2); 
     else if((t1 instanceof SubType2) && (t2 instanceof SubType1)) 
      t1.DoSomething(); 
     else if(...) { 
      t1.DoSomething(); 
      t2.DoSomething(); 
     } 
     else if(...) 
      // ... 
    } 

    public void DoSomething2() { 
     // basically the same 
    } 
} 

由于作用依赖于两种类型的我不能由该方法移动到亚型避免instanceof运算符。有没有一种方法可以改进我的设计,这样我就可以避免使用instanceof?

我知道这里有很多类似的问题,但我想避免使用访问者,因为我有大约20个DoSomething() - 将导致9 * 20实现visit()的方法。

+1

取决于//做一些动作实际上做了什么? – Rehman

+2

这太宽泛了。我们不知道“做某些行动”会发生什么,但更重要的是,我们不知道您要实现什么目标。避免使用'instanceof'的典型方法是正确使用接口。 – Tunaki

+0

为什么你不使用多态?做你的行动 – Husam

回答

1

正确的方式做,这在面向对象的语言是用一种称为“双分派”模式(Googlable,但维基百科上关于这页是不是很大)。

的“追加”的方法,使一个很好的例子:

class Super 
{ 
    abstract void appendTo(Super target); 
    abstract void append(Sub1 source); 
    abstract void append(Sub2 source); 
} 

class Sub1 
{ 
    void appendTo(Super target) 
    { 
     target->append(this); //calls the Sub1 overload 
    } 
    void append(Sub1 source) 
    { 
     ... this is Sub1, source is Sub1 ... 
    } 
    void append(Sub2 source) 
    { 
     ... this is Sub1, source is Sub2 ... 
    } 
} 
class Sub2 
{ 
    void appendTo(Super target) 
    { 
     target->append(this); //calls the Sub2 overload 
    } 
    void append(Sub1 source) 
    { 
     ... this is Sub2, source is Sub1 ... 
    } 
    void append(Sub2 source) 
    { 
     ... this is Sub2, source is Sub2 ... 
    } 
} 
0

这里一个简单的解决方案选项,您可以使用它,使用Generics的类型安全& Polymorphism做到在每个子类

的动作行为
interface SuperType<T> { void doAction(); }; 
class SubType1 implements SuperType<SubType1> { public void doAction(){} }; 
class SubType2 implements SuperType<SubType2> { public void doAction(){} }; 
class SubType3 implements SuperType<SubType3> { public void doAction(){} }; 

class Tuple { 

    //if((t1 instanceof SubType1) && (t2 instanceof SubType3)) 
    //passing params rather than instanceof checking 
    public void doSomething1CaseOne(SuperType<? extends SubType1> t1, SuperType<? extends SubType3> t3) { 
     if(t1 == null || t3 == null) { 
      throw new NullPointerException("Null Params!"); 
     } 
     /** 
     * the method action here 
     * example: switch(t1, t2); 
     */ 
    } 

    //if((t1 instanceof SubType2) && (t2 instanceof SubType1)) 
    public void doSomething1CaseTwo(SuperType<? extends SubType2> t2, SuperType<? extends SubType1> t1) { 
     if(t2 == null || t1 == null) { 
      throw new NullPointerException("Null Params!"); 
     } 
     /** 
     * the method action here 
     * example: t1.doAction(); 
     */ 
    } 
    ... others methods 
} 

现在,这里传递的有效/参数无效的方法的例子:

Tuple tuple = new Tuple(); 
SuperType<SubType1> t1 = new SubType1(); 
SuperType<SubType2> t2 = new SubType2(); 
SuperType<SubType3> t3 = new SubType3(); 

tuple.doSomething1CaseOne(t1, t3); //valid typesafe compilation time 
tuple.doSomething1CaseOne(t1, t2); //invalid typesafe compilation time 

tuple.doSomething1CaseTwo(t2, t1); //valid typesafe compilation time 
tuple.doSomething1CaseTwo(t1, t2); //invalid typesafe compilation time 
+0

但后来我不得不将我的元组类中的字段更改为SuperType t1或SuperType <?扩展了SuperType> t2,在这种情况下,我无法调用t1和t2的方法。 – user4758246