2017-04-11 5 views
1

異なる機能を持つサブクラスを追加して、本当に大きな階層ツリーを持たずに共通の祖先を共有できるクラスを作成しようとすると、少し問題があります。特定のメソッドをオーバーライドする特定のクラスを呼び出すためのデザインパターン

nは、Skillインターフェイスの異なるサブクラスをリストに割り当てて実行するよう呼び出すことを試みています。 SkillのすべてはEventのサブクラスです(ここではありません)。私はちょうどSkillサブクラスを作成するために、右のそれを実行し、それが呼び出す必要がありますし、wheterそれがより効果だろうどのSkill区別しませんかどこ

私の問題はSkillManagerに存在します。

これは私のSkill.classインタフェース

public abstract class Skill 
{ 
    /** 
    * Private shortcut so this code doesn't have to be reused over and over to call 
    * for cooldowns on the skills 
    * @param dp player making the request 
    * @return if the command is available for use 
    */ 
    protected boolean canUse(DPlayer dp){ 
     String name = "skill_"+getName(); 
     if(!dp.getTag(name).isPresent()) 
      return false; 
     if(dp.getTag(name).get().getRemaining() > 0) { 
      dp.sendActionBarCooldown(ChatColor.AQUA + getName(), dp.getTag(name).get().getRemaining()); 
      return false; 
     } 
     return true; 
    } 
    /** 
    * Returns the name of this skills, this should also be the same 
    * name of the class implementing this interface for initialization 
    * propouses 
    * @return name of skills 
    */ 
    public abstract String getName(); 

    /** 
    * Executor to be implemented and replace/add functionality 
    */ 
    public abstract void execute(); 
} 

ですこれはこれは、助けを

public class Sneak extends Skill { 

    @Override 
    public String getName() { 
     return "Sneak"; 
    } 

    @Override 
    public void onSneak(DPlayer dp, PlayerToggleSneakEvent event){ 
     if(dp.getTag("skills_sneak").isPresent()){ 
//DO STUFF 
     } 
    } 
} 

おかげ実装例Sneak.classである私のSkillManager.class

public class SkillManager 
{ 
    private static final SkillManager instance = new SkillManager(); 
    private final List<Skill> SKILLS =new ArrayList<>(); 

    private SkillManager(){} 

    public static SkillManager get(){return instance;} 
    public void registerSkill(Skill s){ 
     SKILLS.add(s); 
    } 
    public void registerSkills(Skill... s){ 
     for(Skill skill : s){ 
      SKILLS.add(skill); 
     } 
    } 
    public void unregisterSkill(String name){ 
     for(Skill skill : SKILLS){ 
      if(skill.getName().equalsIgnoreCase(name)){ 
       SKILLS.remove(skill); 
      } 
     } 
    } 
    public void callEvent(Skill skill) { 
     skill.execute(); 
    } 

} 

です。 EDIT: Eventオブジェクトは私の実装ではなく、上記のイベントに関するデータを含んでいます。 EDIT 2:フローダイアグラムの追加。赤は私がコード化した部分です。ブルーは、私が Flow Diagram

+1

あなたの質問に直接関係はありませんが、あなたの例では 'List スキル 'を静的メンバーにする必要はありません。 –

+0

ありがとう@ChristopheWeis私は完全にそれをmissad – MartinStone

答えて

1

を使用しています構造の一部である、あなたのOOPのコードに2つの大きな問題があります。

  • はあなたのcallEventはあなたを強制的に、すべてのイベントの実装のためのユニークな抽象メソッドに依存しません適切なメソッドを呼び出すオブジェクトのタイプをチェックします。
  • イベントインスタンスのキャストをパラメータとして送信し、呼び出し元のすべてのイベントタイプに無用な依存関係を作成します。

コマンドデザインパターンを使用してください。 onSneak()onBreak()などの代わりに、共通の​​メソッドを使用してください。 Skill.classでは、抽象メソッドとして実行を宣言し、すべての拡張でその実装を記述するようにします。イベントをトリガするために使用されます。 callEvent()にはコードが1行必要です:event.execute(dp);

イベントをインスタンスとしてパラメータとして送信しないでください。インスタンスは独自のプロパティを保持でき、すでに自身を認識しているためです。

PS:あなたの質問ではを最適化しますが、これは実際には最適化ではありません。アーキテクチャを修正することで、コードをより速くすることはほとんどありません。それは、一方で、読みやすく、維持し、より信頼できるものにするでしょう。 早すぎるコードの最適化に注意してください。

+0

'実行(SkillCommand)'が抽象であるように私は 'スキル'を作った。 'SkillComand'は' DPlayer'と 'Event'オブジェクトをカプセル化するクラスです。しかし、コールイベント(SkillCommand)でもう一度問題に遭遇します。ここでは、HashMapから呼び出す必要のある正しいオブジェクトを見つける方法がわからないので、それらをすべて呼び出すと、1人のプレイヤーで実行されるすべてのスキルを意味します。 私の編集を読んでくださいあなたは、コードの 'Event'機能を忘れてしまったと思います。 – MartinStone

+0

すべてのイベントをすべてのスキルに送信し、スキルが自分自身で処理したいイベントを受け取れるようにします。 –

+0

それはそれぞれのスキルを巨大にするでしょうか? 私が現在使っているコードを編集しました。私はちょうどスキルごとにチェックを実装する必要がありますか? – MartinStone

関連する問題