2011-07-20 8 views
2

私は、構成可能なスキルを持つ忍者がいます。設定可能とは、プログラムが設定ファイルを読み込んで実行時に追加することです。すなわち:問題別のデザインに関する質問

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

これらのスキルは、Ninjaクラスに機能を動的に追加する必要があると仮定します。同様に、NinjaにHigh Jumpスキルを設定する場合、クラスはCanHighJumpインターフェイスに従い、メソッドとしてpublic void highJump()を実行する必要があります。

これについては、私が考えることができる2つの方法があります。私の最初の反応は、StringカラーのNinjaクラスを使用し、Reflectionを使用して機能を追加することです。しかし、今では、リレーショナルデータベースを使っても実現できることが分かりました。文字列カラーの忍者クラスをお持ちで、忍者とスキルとの関連のあるオブジェクトを忘れてください。スキルをチェックする必要がある場合は、クラスが使用できるスキルを取得するデータベースを呼び出してください。それらは私が思いつくことができる唯一の2つの真のダイナミックな解決策であり、私はそれぞれのデザインの長所/短所を理解することはできません。私は、データベースソリューションがはるかに拡張可能であると感じていますが、コーディングの際にリフレクション方式が私にとって最も理にかなっています。 Ninjaが持っているスキルを照会する必要はありません。インターフェースを簡単に確認できるからです。

私は誰かが私にこの問題の標準的な設計ソリューションについての洞察力を与えることができると願っています。それが私が思いついた2つのうちの1つであろうと、私が考えなかったものであろうと。

答えて

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(); 
    } 
} 

このパターンを使用すると、オブジェクトに実際にオブジェクトを実装することなく、新しい機能をオブジェクトに追加できます。クライアントはmyNinja.getSkill(IHighJumpCapable.class)(忍者にこのスキルがある場合)を呼び出すとIHighJumpCapableのインスタンスを取得し、そうでない場合はnullを返します。その後、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(); 
     } 

} 
関連する問題