2011-07-20 32 views
2

假設我有一個具有某些可配置技能的忍者。通過可配置,我的意思是程序讀入配置文件並在運行時添加它們。即:另一個特定於問題的設計問題

Ninja: 
    color: Red 
    Skills: 
    - High Jump 
    - Invisibility 

現在,假設這些技能需要動態添加功能到忍者類。如果我們將Ninja配置爲具有跳高技能,那麼該類需要遵循CanHighJump接口,並使用public void highJump()作爲方法。

現在有兩種方法我可以考慮去做這件事。我的第一反應是將一個忍者類與字符串顏色,然後使用反射來添加功能。但是,現在我意識到我也可以通過關係數據庫來實現。有一個帶有String顏色的忍者班,忘記任何有關忍者與技能的對象 - 相反,無論何時我需要檢查一項技能,只需撥打數據庫即可獲取該班可以使用的技能。這些是我能想出的唯一兩個真正動態的解決方案,我無法理解每個設計的優缺點。我有一種感覺,數據庫解決方案的可擴展性要高得多,但反射方法在編碼時最適合我。無需查詢忍者擁有哪些技能,因爲我可以輕鬆檢查界面。

我希望有人可以給我一點關於這個問題的標準設計解決方案的見解。無論是我提出的兩個之一,還是更可能是我沒有想到的東西。

回答

2

看來你正在尋找的是接近Capability Pattern

public interface IHasSkills { 
    public <T> getSkill(Class<T> skill); 
} 

public interface ICanAddSkills extends IHasSkills { 
    public void addSkill(ISkill skill) 
} 

public class Ninja implements ICanAddSkills { 
    private List<ISkill> _skills; 

    public void addSkill(ISkill skill) { 
     _skills.Add(skill); 
    } 

    public <T> GetSkill(Class<T> skillType) { 
     for(ISkill skill : _skills) { 
      if(skill instanceof skillType) return skill; 
     } 
     return null; 
    } 
} 

public interface ISkill{} 

public interface IHighjumpSkill extends IHighJumpCapable{ 
    public void highJump(); 
} 

public class NinjaHighJumpSkill implements IHighJumpCapable{ 
    private Ninja _canHighJump; 
    public NinjaHighJumpSkill(Ninja ninja) { 
     _canHighJump = ninja; 
    } 

    @Override 
    public void highJump() { 
     //Note that this could be combined with the [Property Pattern][2] 
     //(which was referenced in another answer) to set/get arbitrary 
     //properties on the ninja. 
     _canHighJump.DoWhateverAHighJumpDoes(); 
    } 
} 

您可以使用此模式向對象添加新功能,而無需在對象中實際實現它們。如果忍者擁有此技能,則客戶將獲得IHighJumpCapable的實例,否則爲空。然後可以調用IHighJumpCapable上的highJump()方法。

public static void Main(String args[]) { 
    Ninja ninja = new Ninja(); 
    ninja.AddSkill(new NinjaHighJumpSkill(ninja)); 
    IHighJumpCapable canHighJump = ninja.GetSkill(IHighJumpCapable.class); 
    canHighJump.highJump(); 
} 
+0

是的,這似乎是財產模式正在得到什麼,只是更具體的問題。感謝您花時間編寫代碼。我最終會這樣做。我從來沒有想過HasSkills - > CanAddSkills之前的關係。這非常靈活。 – Phil

0

請參閱"Universal Design Pattern"上的此博客文章,其中討論了對象具有動態添加到其中的屬性的系統。

+0

看着它現在 - 感謝。 – Phil

1

這是Ryan建議的一種擴展。如果需要,下面的方法將使忍者執行技能,而不必詢問和檢查技能類型。

看看這增加值 -

public class Ninja implements ICanAddSkills { 
private List<ISkill> _skills; 

public void addSkill(ISkill skill) { 
    _skills.Add(skill); 
} 

public <T> getSkill(Class<T> skillType) { 
    for(ISkill skill : _skills) { 
     if(skill instanceof skillType) return skill; 
    } 
    return null; 
    } 
} 

    public interface ISkill{ 
     public void performSkill(); 
    } 

public interface IHighjumpSkill extends ISkill,IHighJumpCapable{ 
    public void highJump(); 
} 

public class NinjaHighJumpSkill implements IHighjumpSkill{ 
    private Ninja _canHighJump; 
    public NinjaHighJumpSkill(Ninja ninja) { 
     _canHighJump = ninja; 
    } 

    @Override 
    public void highJump() { 
     _canHighJump.DoWhateverAHighJumpDoes(); 
    } 

    // delgate to whatever this skill can do 
    @Override 
    public void performSkill() { 
     highJump(); 
    } 
} 


public static void Main(String args[]) { 
    Ninja ninja = new Ninja(); 
    ninja.AddSkill(new NinjaHighJumpSkill(ninja)); 
    // loop through skills and perform actions using performSkill() 

    for(ISkill skill : _skills) { 
      skill.performSkill(); 
     } 

}