Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在这种情况下,有没有办法避免if-else和dynamic cast?_Java_Oop_Design Patterns_Dynamic Cast - Fatal编程技术网

Java 在这种情况下,有没有办法避免if-else和dynamic cast?

Java 在这种情况下,有没有办法避免if-else和dynamic cast?,java,oop,design-patterns,dynamic-cast,Java,Oop,Design Patterns,Dynamic Cast,例如,对于一个游戏,我有一些技能,即数据对象: public interface Skill{ public String getName(); } public class Attack implements Skill{ public String getName(){ return "Attack"; } public int power; } public class Speak implements Skill{ public String getName(

例如,对于一个游戏,我有一些技能,即数据对象:

public interface Skill{
public String getName();
}

public class Attack implements Skill{
    public String getName(){ return "Attack"; }
    public int power;
}

public class Speak implements Skill{
    public String getName(){ return "Speak"; }
    public String speech;
}

为了在游戏中应用这些技能,我需要一些相应技能的技能处理者:

public interface SkillHandler{
    public void apply(Skill skill);
}

public class AttackHandler{
    @Override
    public void apply(Skill skill){
        Attack attack=(Attack)skill;
        Player player=Global.getPlayer();
        Enemy enemy=Global.getEnemy();
        enemy.hp=enemy.hp-attack.power;
        //some other code for follow up handle
    }
}

public class SpeakHandler{
    @Override
    public void apply(Skill skill){
        Speak speak=(Speak)skill;
        Label label=new Label(speech);
        this.displayOnTop(label);
    }
}
我为每项技能使用一名SkillHandler,因为我不希望技能依赖于SkillHandler,PlayerTackStateHandler将应用每项技能:

public class PlayerAttackStateHandler{
    public PlayerAttackHandler(){
        Skill[] skills=Global.getSkills();
        for(int i=0;i<skills.length;i++){
            SkillHandler skillHandler=null;

            if(skills[i].getName().equals("Attack")){
                skillHandler=new AttackHandler();
            }else if(skills[i].getName().equals("Speak")){
                skillHandler=new SpeakHandler();
            }

            skillHandler.apply(skills[i]);
        }
    }
}
公共类PlayerTackStateHandler{
公共玩家处理程序(){
Skill[]skills=Global.getSkills();
对于(inti=0;i将攻击和说话视为某些代理可能拥有的能力

<>我会考虑测试能力/特性:

interface Attacking { void attack(); }
interface Speaking { void speak(); }

Animal animal = ...

Optional<Attacking> attacker = animal.lookup(Attacking.class);
attacker.ifPresent(a -> a.attack());

Optional<Speaking> speaker = animal.lookup(Speaking.class);
speaker.ifPresent(sp -> sp.speak());
接口攻击{void attack();}
接口说话{void speak();}
动物。。。
可选攻击者=animal.lookup(Attacking.class);
攻击者.ifPresent(a->a.attack());
可选扬声器=animal.lookup(Speaking.class);
speaker.ifPresent(sp->sp.speak());
Animal不需要实现任何接口,但您可以查找(查找或作为)功能。这在将来是可扩展的,动态:可以在运行时更改

实施为

private Map<Class<?>, ?> map = new HashMap<>();

public <T> Optional<T> lookup(Class<T> type) {
     Object instance = map.get(type);
     if (instance == null) {
         return Optional.empty();
     }
     return Optional.of(type.cast(instance));
}

<S> void register(Class<S> type, S instance) {
    map.put(type, instance);
}
private Map=new HashMap();
公共可选查找(类类型){
对象实例=map.get(类型);
if(实例==null){
返回可选的.empty();
}
返回可选的.of(type.cast(instance));
}
无效寄存器(类类型,S实例){
map.put(类型、实例);
}

该实现执行安全的动态强制转换,因为register确保了(键、值)条目的安全填充。

您的实现似乎与访问者模式有很多共同之处,如下所示:

public interface ISkillable //this is your Skill
{
    public int GetPower();
    public string GetSpeak();
}

public interface IVisitable //player or npc
{
    public void Accept(IVisitor visitor)
}

public interface IVisitor //AttackHandler or SpeakHandler
{
    public void ApplySkill(ISkillable skillable)
}

public class Player implements ISkillable, IVisitable
{
    ...
    public void Accept(IVisitor visitor)
    { 
        visitor.Visit(this); 
    }
}

public class AttackVisitor implements IVisitor
{
    public void Visit(ISkillable skillable)
    {
        //do something with power
    }
}
然后举例说明如何使用它

player.Accept(new AttackVisitor(/*you can provide additional info like enemy*/));
player.Accept(new SpeakVisitor());

如果你愿意为Skill添加一个样板函数,你应该研究访客模式。为什么不添加到
Skill
?所有技能实现的另一个界面可以接受吗?你已经有了一个
全局
功能,这不是一个完美的设计。也许访客模式中skills可以访问p层或npc并应用它们的逻辑。我不明白为什么您不希望在Skill和SkillHandler之间有依赖关系。只需在Skill中实现SkillHandler并调用apply将避免if else语句。为什么不使用工厂类进行SkillHandler初始化。因此,如果还添加了新的Skill或SkillHandler,您将不更改PlayerTackStateHandler类。