用于调用特定类的设计模式覆盖特定的方法

问题描述:

所以我在尝试创建一个类时可能会附加具有不同功能的子类并共享一个共同的祖先而没有真正的大型层次树。用于调用特定类的设计模式覆盖特定的方法

我想要做的是nSkill接口的不同子类,它们被分配在一个列表中,然后调用执行。所有在SkillEvent(不在这里)的子类。

我的问题在于SkillManager在这里我就不如何区分哪些Skill应该打电话wheter这将是更大的影响只是创造Skill子类,并执行它的权利呢。

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

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

} 

这是Sneak.class示例实现

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 
     } 
    } 
} 

感谢您的帮助。 编辑: Event对象来自不是我的实现,并包含有关所述事件的数据的API调用 编辑2:添加流程图。红色是我编码的部分。蓝色是结构的一部分,我使用 Flow Diagram

+1

与您的问题没有直接关系,但在您的示例中,没有必要使'List SKILLS'成为静态成员。 –

+0

谢谢@ChristopheWeis我完全错过了 – MartinStone

有你的OOP代码有两个主要问题:

  • callEvent不依赖于你的所有事件的实现独特的抽象方法,迫使你检查对象的类型以调用正确的方法。
  • 您将事件实例的强制转换作为参数发送给自己,从而在调用者中使用您所有的事件类型创建无用的依赖关系。

使用指令设计模式;而不是有onSneak()onBreak()等,只是使用普通的​​方法。在你的Skill.class中,声明execute为抽象方法,迫使你在所有extends中编写它的实现。它将被用来触发事件。 callEvent()现在只需要一行代码:event.execute(dp);

您不应该将事件作为参数发送给自己,因为作为一个实例,它可以保存自己的属性并且已经知道自己。

PS:您可以在您的问题中将此优化称为,但这不是真正的优化。修复这个架构很难让你的代码更快。另一方面,它将使读取,维护和更可靠更加容易。 请注意过早的代码优化。

+0

我已经使'技巧',使'执行(SkillCommand)'是抽象的。 'SkillComand'是一个封装了'DPlayer'和'Event'对象的类。然而,我在'callEvent(SkillCommand)'处再次遇到问题,我不知道如何从HashMap中找到我需要调用的正确对象并调用它们,这意味着所有的技能都将在1个玩家上执行。 请阅读我的编辑我想你错过了代码中的'Event'功能。 – MartinStone

+0

将所有事件发送给所有技能,并让技能选取他们想要处理的事件。 –

+0

这会使每个技能都变得巨大吗? 我编辑了我目前使用的代码。我是否应该在每项技能上实施检查,每次调用1项技能实际上是调用50次以上,而不仅仅是做一次检查,然后什么都不做? – MartinStone