2014-05-09 71 views
1

這是某種設計模式問題,我想。如何在Java中抽象不同的返回類型?

我想爲幾個操作(輸入+處理邏輯+輸出)建模爲實現某個IOperation接口的類。

每個操作可能有不同的輸入參數和不同的輸出參數。

我可以使用每個構造函數爲每個操作指定不同的輸入。

但我想以正交的方式爲每個類獲得不同的輸出,而不必將接口轉換爲具體的類。

對此的明顯方法是將[1]投射到具體類並調用返回所需結果的特定方法,或[2]將結果包裝到某個OperationResult對象中,而這又會需要向下轉換或一些元數據信息+提取器代碼。

我想避免處理反射或向下轉換或元數據解釋。

在Java中有這種情況的任何已知設計嗎?這將是一個很好的方法?

更新 - @Laf,這裏有一些具體的例子。我想提取「C」

interface IOperation{ 
    void execute(); 
} 

public class AddOp implements IOperation{ 

    private int a; 
    private int b; 
    private int c; 

    public AddOp(int a, int b){ 
     this.a = a; 
     this.b = b; 
    } 

    @Override 
    public void execute() { 
     this.c = this.a + this.b; 
    } 

} 

public class AndOp implements IOperation{ 

    private boolean a; 
    private boolean b; 
    private boolean c; 

    public AndOp(boolean a, boolean b){ 
     this.a = a; 
     this.b = b; 
    } 

    @Override 
    public void execute() { 
     this.c = this.a && this.b; 
    } 

} 
+0

您是否考慮過使用泛型? – Laf

+0

聽起來不錯。 @Laf什麼是你的方法與泛型? – Leo

+0

回答Noor,這是真的,但如果我沒有在這個接口中的每種不同類型的結果的方法,我不得不倒下它到具體的實現。(-1不是我 - 我不會downvote我自己的問題的答案) – Leo

回答

4

看起來你可以使用double dispatching

不是返回一個值(即Object),而是返回void並將參數傳遞給要將結果放入的目標對象。

interface ResultProcessor { 
    processTypeA(A item); 
    processTypeB(B item); 
    processTypeC(C item); 
} 

interface InputProcessor { 
    processInput(ResultProcessor target); 
} 

class ConcreteInputProcessorA { 
    processInput(ResultProcessor target) { 
     A result = ...; // Do something 
     target.processTypeA(result); 
    } 
} 

class ConcreteInputProcessorB { 
    processInput(ResultProcessor target) { 
     B result = ...; // Do something 
     target.processTypeB(result); 
    } 
} 

class ConcreteInputProcessorC { 
    processInput(ResultProcessor target) { 
     C result = ...; // Do something 
     target.processTypeC(result); 
    } 
} 

更新:比如跟你的新編輯的代碼你可能會寫:

public class AddOp implements IOperation{ 

    private int a; 
    private int b; 
    private int c; 

    public AddOp(int a, int b){ 
     this.a = a; 
     this.b = b; 
    } 

    @Override 
    public void execute(Executor ex) { 
     this.c = this.a + this.b; 
     ex.executeAddOp(this); 
    } 
} 

public class Executor { 
    public void executeAddOp(AddOp op) { 
     System.out.println("Executing an AndOp... " + op); 
    } 
} 
+0

是的,訪問者模式的第二個一半救援:-) – dasblinkenlight

+0

@ vz0這聽起來不錯。就我而言,我希望每個實現ResultProcessor的類只實現一種方法。我怎麼能執行這個?拋出所有其他類型的「不受支持」異常? – Leo

+0

@Leo更新回答 – vz0

1

一種可能的方法是這樣的:

private <T extends SomeCommonAncestor> T someMethod(InputParamObject i, 
     Class<T> respClass) {...} 

你仍然需要一些常用的接口/抽象類返回的對象,你需要指定執行/子類作爲方法的一部分。

希望這會有所幫助。

[編輯]

public interface IOperation{ 

     public <T extends ResultObject> T execute(Class<T> respClass); 
} 

public class AndOp implements IOperation{ 

    private boolean a; 
    private boolean b; 
    private boolean c; 

    public AndOp(boolean a, boolean b){ 
     this.a = a; 
     this.b = b; 
    }  


    @Override 
    public <T extends ResultObject> T execute(Class<T> respClass) 
    { 
     BoolWrap ret = new BoolWrap (a & b); 
     return ret; 
    } 

} 

class BoolWrap extends ResultObject { 
... 
} 

class AndOpTest { 
    public void testIt() 
    { 
     AndOp op = new AndOp (false, true); 
     BoolWrap result = op.execute (BoolWrap.class); 
     //Profit? 
    } 
} 
+0

嗨@demaniak,我已經在另一個上下文中使用過它,它的工作非常好。但是我不清楚在這個問題背景下我將如何使用它。我試過把這個方法添加到IOperation中,但我無法弄清楚如何處理每個具體的操作實現。你打算如何使用這個解決方案?謝謝。 – Leo

+0

我會編輯我的答案,嘗試並在幾分鐘內澄清;) – demaniak

+0

謝謝@demaniak。如果可以的話,我會接受你和vz0的答案。特別是,你的洞察力對我在這裏提出的答案很重要,我非常喜歡。但是我必須同意vz0的答案告訴我,當一個簡單的控制反轉(我們可以稱之爲IoC?)能夠以更好的方式工作時,我是在錯誤的路徑上試圖單獨強制執行輸入和輸出。所以,我想感謝你的所有時間。當然,我已經提出了你的答案。謝謝 – Leo

1

我自己來到了另一個有趣的方法,考慮貼在這裏的一些建議之後。

我不會接受它作爲最終答案,因爲我認爲這對於那些花時間試圖幫助的人來說並不公平。但我想分享它。

public class SO { 

    public static void main(String[] args){ 
     new SO().new Example().exec(); 
    } 

    interface IResponse{ 
     //just a tagging interface 
    } 

    public class IntegerResponse implements IResponse{ 
     private int i; 

     private IntegerResponse(int i) { 
      this.i = i; 
     } 

     protected int getI() { 
      return i; 
     } 

    } 

    public class BooleanResponse implements IResponse{ 
     private boolean b; 

     private BooleanResponse(boolean b) { 
      this.b = b; 
     } 

     protected boolean isB() { 
      return b; 
     } 

    } 

    interface IOperation<X extends IResponse>{ 
     void execute(); 
     <X extends IResponse> X someMethod(); 
    } 



    public class AddOp implements IOperation<IntegerResponse>{ 

     private int a; 
     private int b; 
     private int c; 

     public AddOp(int a, int b){ 
      this.a = a; 
      this.b = b; 
     } 

     @Override 
     public void execute() { 
      this.c = this.a + this.b; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     public IntegerResponse someMethod() { 
      return new IntegerResponse(this.c); 
     } 

    } 

    public class AndOp implements IOperation<BooleanResponse>{ 

     private boolean a; 
     private boolean b; 
     private boolean c; 

     public AndOp(boolean a, boolean b){ 
      this.a = a; 
      this.b = b; 
     } 

     @Override 
     public void execute() { 
      this.c = this.a && this.b; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     public BooleanResponse someMethod() { 
      return new BooleanResponse(this.c); 
     } 

    } 

    public class Example{ 
     public void exec(){ 
      IOperation<?> op = new AndOp(true,false); 
      BooleanResponse resp = op.someMethod(); 
      System.out.println(resp.isB()); 
     } 
    } 
} 
+0

是的,這也可以工作。祝你好運! – demaniak