2015-11-01 65 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