Reputation: 184
So I am having a bit of a problem when trying make a class that can be appended subclasses with different functionalities and share a common ancestor without having really big hierarchy trees.
What I am trying to do is make n
different sub classes of the Skill
interface which are allocated in a list and then called to be execute. All the in Skill
are sublclasses of Event
(not here).
My problem resides in SkillManager
where I don't how to differentiate which Skill
it should call and wheter it would be more effect just to create the Skill
subclass and execute it right then.
This is my Skill.class interface
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();
}
This is my 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();
}
}
This is Sneak.class the example implementation
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
}
}
}
Thanks for the help.
EDIT:
The Event
objects are derived from api calls not from my implementation and contain data about said event
EDIT 2: Adding flow diagram. Red is the parts I coded. Blue is part of the structure I am using
Upvotes: 1
Views: 296
Reputation: 6463
There are two major issues in your OOP code:
callEvent
doesn't rely on a unique abstract method for all your events implementations, forcing you to check the type of object to call the right method.Use the Command Design Pattern; instead of having onSneak()
, onBreak()
, etc, just use a common execute()
method. In your Skill.class
, declare execute as abstract method, forcing you to write its implementation in all the extends. It will be used to trigger the event. callEvent()
now needs just one line of code: event.execute(dp);
.
You shouldn't send the event to itself as a parameter since, as an instance, it can hold its own properties and is already aware of itself.
PS: You call this optimization in your question, but this is not really optimization. Fixing the architecture will hardly make your code faster. It will, on the other hand, make it easier to read, maintain, and more reliable. Beware of premature code optimization.
Upvotes: 1