2012-07-25 83 views
1

我有兩個具有相同的實現,但名稱不同的類。它們產生的,我無法對它們進行修改:如何實現對兩個相同類的引用?

public class Foo { 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

public class Bar { 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

我需要填充這些類的數據,並且由於它們是相同寧願用一個類或引用做,然後轉換爲(或希望解決方案更優雅)Foo或酒吧根據需要。概念上:

FooOrBar fob = ????; 
fob.setName("XYZ"); 

Foo f = fob.(???); 
Bar b = fob.(???); 

我已經研究過泛型,但它似乎是當你真的不知道你將在什麼類上運行。我有可能有某種類型的類或參考達到此目的嗎?

7月26日編輯:

道歉,如果這是不好的形式後續UPS這樣的,我可以張貼新的如果需要的話。我正在實施Tomasz的Adapter模式,但我的最後一步與他不同。我需要接口對象的條件賦值。下面是我所擁有的,到目前爲止我沒有收到任何錯誤或警告,但我想知道這是不是出於某種原因的好習慣?也許我應該使用反射或泛型來確定接口的類?這將是一種只有我的代碼會調用的方法,我會知道這個情況。我已經搜索了條件接口的分配,但沒有找到太多。

FooOrBar fob; //interface 

if (condition true) { 

    fob = new FooAdapter(); //FooAdapter implements FooOrBar 
} else { 
    fob = new BarAdapter(); //BarAdapter implements FooOrBar 
} 

fob.setName("XYZ"); 
+0

撰寫超,讓富,酒吧擴展它(或)寫的接口和讓Foo/Bar實現它。 – kosa 2012-07-25 17:51:03

+1

我同意thinksteep,但如果你不能修改類以擺脫重複,我猜你不能修改它們來實現一個接口。這些類是否真的是相同的,如果是這樣,爲什麼它們是以這種方式創建的? – Bobulous 2012-07-25 17:53:18

+0

這些類是相同的,它們是通過目標系統的wsdl消耗創建的,我無法修改wsdl。目標系統爲資源創建和更新生成單獨的消息,但它是完全相同的數據。 – user640118 2012-07-25 18:02:23

回答

2

你在找什麼叫做,在Java中不支持。嘗試動態語言,如

在Java中,假設您無法修改FooBar,您需要一個適配器模式。首先在FooBar創建一個抽象:

public interface FooOrBar { 
    String getName(); 
    void setName(String name); 
} 

,有兩個適配器這樣的(BarAdapter幾乎是一樣的):

public class FooAdapter implements FooOrBar { 

    private final Foo foo; 

    public FooAdapter(Foo foo) { 
     this.foo = foo; 
    } 

    public String getName() { 
     return foo.getName(); 
    } 

    public void setName(String name) { 
     foo.setName(name); 
    } 

} 

現在,你可以說:

FooOrBar fob = new FooAdapter(foo); 
FooOrBar fob2 = new BarAdapter(bar); 

fob.setName("XYZ"); 

我將離開提取實際價值給你(你真的需要它嗎?)

+0

很高興看到別人使用設計模式!不要忘記實現界面。 – LastStar007 2012-07-25 17:59:59

+0

感謝您的博文,相當有幫助。我已經更新了我的帖子,並提供了有關解決方案最終步驟的澄清問題。 – user640118 2012-07-26 19:24:11

+0

@ user640118:我不太明白你的新要求,是不是夠了:'FooOrBar fob =(condition true)?新的FooAdapter(新的Foo()):新的BarAdapter(新的Bar())'? – 2012-07-26 19:30:40

0

我不完全確定你的需求是什麼,但你有沒有考慮創建一個包含foo和bar實例的包裝類的最簡單的解決方案?

class FooOrBar { 
    private Foo foo; 
    private Bar bar; 

    public setName(name) { 
     if (foo != null) foo.name = name; 
     if (bar != null) bar.name = name; 
    } 
} 

您可以根據需要添加驗證以確保只有一個項目被單個包裝器引用。

1

您可以創建一個標記類。

這被認爲是一種反模式,因爲它們不如使用類層次結構,但由於您無法控制層次結構,所以沒有多少選擇餘地。

這給你的好處是知道什麼發送通過您的web服務,而不訴諸於instanceof

class FooBar { 
    public static enum Mode { FOO, BAR } 
    Foo foo; 
    Bar bar; 
    Mode mode; 
    FooBar(Foo foo) { 
     mode = Mode.FOO; 
     this.foo = foo; 
    } 
    FooBar(Bar bar) { 
     mode = Mode.BAR; 
     this.bar = bar; 
    } 

    public String getName() { 
     switch(mode) { 
      case FOO: foo.getName(); 
      case BAR: bar.getName(); 
      default: throw new IllegalStateException(); 
     } 
    } 

    public void setName(String name) { 
     switch(mode) { 
      case FOO: foo.setName(name); return; 
      case BAR: bar.setName(name); return; 
      default: throw new IllegalStateException(); 
     } 
    } 
    public Mode getMode() { return mode; } 
} 
1

想必您無法控制生成的類(否則,這將是微不足道的!)。

另一種方法是創建一個輔助類和使用反射來設置每個屬性,你需要設置(見How do I invoke a Java method when given the method name as a string?

+0

您可以,但應儘可能避免反思,因爲它會使代碼複雜化。 Upvote創造力。 – LastStar007 2012-07-25 18:05:46

+0

它不僅使代碼複雜化,而且會降低編譯時間的完整性。 – corsiKa 2012-07-25 18:07:17

+0

一般都是如此,但是這裏的反射會更復雜嗎?無論如何,我絕對同意丟失編譯時檢查是一個主要的缺點。 – hythlodayr 2012-07-25 18:42:31

相關問題