2015-06-20 76 views
0

我想找到一種方法來繞過使用instanceof。我創建了一個具有WeaponItem和BodyItem等多個子類的類Item。現在我想做一個諸如equip(Item)之類的調用,它應該自行確定它應該調用哪個重載函數,比如equip(BodyItem)。避免Java的實例

有沒有辦法繞過這種情況下使用instanceof以及你會推薦什麼?我聽說在大多數情況下使用instanceof是不好的做法,因此我想知道替代方案是什麼。

代碼:

inv.equip(it); // inv = inventory object, it = Item 

庫存類中的裝備功能的一個例子,說明我最好希望它

public void equip(HelmItem it) 
{ 
    if (it != this.getHelm()) 
    { 
     this.setHelm(it); 
    } 
} 

之前,我怎麼過的:

public void equip(Item it) 
{ 
    if (it instanceof WeaponItem) 
    { 
     if (it != this.getWeapon()) 
     { 
      this.setWeapon((WeaponItem) it); 
     } 
    } etc for all subclasses of item 
} 
+2

查找double-dispatch和訪問者模式 –

+0

[避免Java中的instanceof]可能的重複(http://stackoverflow.com/questions/15457623/avoid-instanceof-in-java) – Qiu

+1

你可以分享你的代碼嗎正在嘗試? –

回答

3

確實,這可以通過訪問者模式解決。

但是,它不一定是一個完整的訪問者,而是一個簡化的變體。您可以在庫存傳遞到項目,讓項目爲所欲爲吧:

abstract class Item { 
    public abstract void equip(Inventory inv); 
} 

class HelmItem extends Item { 
    @Override 
    public void equip(Inventory inv) { 
     inv.setHelm(this); 
    } 
} 

class WeaponItem extends Item { 
    @Override 
    public void equip(Inventory inv) { 
     inv.setWeapon(this); 
    } 
} 

然後你可以叫:

it.equip(inv) 

沒有instanceof操作。

+0

這真的解決了問題!感謝您分享您的想法!它仍然相當違反直覺,因爲語義上說一件物品裝備了庫存,但它作爲解決方案起作用,所以謝謝! :D –

+0

是的,這可以通過保留'inv.equip(it)'方法來克服,但是在實現它時可以調用'it.equip(this)'。通過這種方式,您可以將物品添加到庫存的集中位置,這很好,因爲它符合DRY,並且您還可以在其中執行其他操作,例如計算添加的物品,檢查庫存是否已滿等。 –

+0

雖然我們說過類似的事情,但你做得更好,並提供了一個完整的例子。 +1 – christopher

2

爲什麼不把方法在Item具體類,它可以裝備自己?這有點直觀,但它可以解決你的問題。

public class SomeConcreteItem extends Item { 
    public void equip(Body body) { 
     // Just an example. 
     body.getSections().get(0).equip(this); 
    } 
} 

這樣,具體的實現知道如何裝備自己和使用它的類不關心。您可以通過Item超類來引用它,並且假定Item超類有一個抽象方法public void equip(Body body);,那麼您不需要知道具體實現,因此不需要instanceof運算符。

上引入一個設計模式

記下您應該謹慎引入設計模式。人們有一種不良習慣,即直接跳躍到一種複雜的模式來解決問題,當真正簡單一些,並且(在我看來)更加優雅的時候。