说我有一个具有某些可配置技能的忍者。通过可配置,我的意思是程序读入配置文件并在运行时添加它们。即:
Ninja:
color: Red
Skills:
- High Jump
- Invisibility
现在,假设这些技能需要动态地为Ninja类添加功能。如果我们将Ninja配置为具有跳高技能,那么该类需要遵循CanHighJump接口,使用public void highJump()作为方法。
现在我有两种方法可以考虑这个问题。我的第一反应是使用String颜色的Ninja类,然后使用Reflection添加功能。但是,现在我意识到我也可以通过关系数据库来实现。拥有一个带有String颜色的Ninja类,忘记任何与Ninjas相关的对象 - 相反,每当我需要检查技能时,只需调用数据库检索类可以使用的技能。这是我能提出的唯一两个真正动态的解决方案,我无法理解每个解决方案的设计优缺点。我有一种感觉,数据库解决方案将更具可扩展性,但反射方法在编码时对我来说最有意义。无需查询忍者拥有哪些技能,因为我可以轻松检查界面。
我希望有人能够对这个问题的标准设计解决方案给我一些见解。无论是我想出的两个中的一个,还是更有可能是我没想到的东西。
答案 0 :(得分:3)
您正在寻找的内容似乎接近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
时将获得myNinja.getSkill(IHighJumpCapable.class)
的实例,否则为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();
}
答案 1 :(得分: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();
}
}