2016-03-28 52 views
3

我想在本地庫的類型中調用外部供應商的api方法。供應商的方法以字符串的形式進行設置,該字符串可以採用多個值,例如"Cat""Dog"。我從我喜歡的類型執行映射到供應商的設置字符串這樣的:執行從類型層次結構到值集合的一對一映射的高效設計模式

public class Program { 
    interface LocalType {} 
    static class LocalCat implements LocalType {} 
    static class LocalDog implements LocalType {} 

    // Calls some API to get the animal's sound 
    interface AnimalSounds { 
     void playSound(LocalType t); 
    } 

    // Vendor-specific implementation 
    static class VendorSounds implements AnimalSounds{ 
     private static VendorAPI api = new VendorAPI(); 
     @Override public void playSound(LocalType t) { 
      // Map local type to vendor setting 
      if (t instanceof LocalCat) 
       api.vendorMethod("Cat"); 
      else if (t instanceof LocalDog) 
       api.vendorMethod("Dog"); 

     } 
    } 

    // API defined externally by vendor (reproduced here for illustration) 
    static class VendorAPI { 
     static void vendorMethod(String type) { 
      // Do something 
     } 
    } 

    public static void main(String[] args) { 
     AnimalSounds s = new VendorSounds(); // Choose vendor 
     s.playSound(new LocalCat()); // For example 
    } 
} 

這裏"Cat""Dog"是供應商特定的設置;我稍後可能會更改爲法國供應商,其中這兩個分別是"Chat""Chien"。因此,爲了避免將供應商特定的信息添加到LocalType層次結構中,每當我更換供應商時都必須更改該層次結構,我將該映射隱藏在某種適配器AnimalSounds(作爲一個供應商的示例添加了VendorSounds)。

但是instanceof的級聯味道對我來說可能是糟糕的設計,或許有一種更優雅的方式來完成這個我忽略的方法嗎?

回答

2

如果你想完全保留映射本地數據類型之外,你可以建立一個Map<Class,String>,並用它來代替instanceof基於條件語句鏈:

static final Map<Class,String> vendorMethodMap = new HashMap<>; 
static { 
    // The data for this map could come from a configuration file of sorts 
    vendorMethodMap.put(LocalCat.class, "Cat"); 
    vendorMethodMap.put(LocalDog.class, "Dog"); 
} 

現在你playSound法會是這樣的:

@Override public void playSound(LocalType t) { 
    api.vendorMethod(vendorMethodMap.get(t.getClass())); 
} 
1

要在一個更一般的方式解決這個問題,你可以使用訪問者模式。具體元素類實現接受訪問者接口的類:

public class Program { 

    interface LocalTypeVisitor { 
     void visit(LocalDog dog); 
     void visit(LocalCat cat); 
    } 

    interface LocalType { 
     void accept(LocalTypeVisitor visitor); 
    } 
    static class LocalCat implements LocalType { 
     @Override public void accept(LocalTypeVisitor visitor) { 
      visitor.visit(this); 
     } 
    } 
    static class LocalDog implements LocalType { 
     @Override public void accept(LocalTypeVisitor visitor) { 
      visitor.visit(this); 
     } 
    } 

    // API defined externally by vendor (reproduced here for illustration) 
    static class VendorAPI { 
     void vendorMethod(String type) { 
      // Do something 
     } 
    } 

    interface Vendor extends LocalTypeVisitor {} 

    // Vendor-specific implementation 
    static class VendorSounds implements Vendor { 
     private static VendorAPI api = new VendorAPI(); 
     @Override public void visit(LocalCat cat) { 
      api.vendorMethod("Cat"); 
     } 
     @Override public void visit(LocalDog dog) { 
      api.vendorMethod("Dog"); 
     } 
    } 

    public static void main(String[] args) { 
     Vendor s = new VendorSounds(); // Choose vendor 
     new LocalCat().accept(s); // For example 
    } 
} 

但它很難創造新的LocalType實現,因爲它通過漣漪所有參觀者。所以仔細考慮一下。

+0

它是如何解決問題的? – AdamSkywalker

+0

通過雙重調度 –

+1

我喜歡這個,因爲它允許訪問者可能返回一個複雜的類型而不是'void' – ScarletPumpernickel