避免复合模式中的instanceof

时间:2013-04-24 09:51:23

标签: java

我正在为大学设计一个游戏项目。在这个游戏中可以发生几种效果,一种效果可以影响另一种效果的行为。现在,其中一个想法是使用复合模式,它最初看起来像一个坚实的解决方案。这里最大的问题是效果的行为方式取决于它与之结合的效果,我们看到解决这个问题的唯一方法是使用我们想要不惜一切代价避免使用的.getClass()或instanceof。

设计此问题有哪些方法?

编辑(一个小例子): 我没有明确的代码示例,但我将尝试使用以下示例澄清一点:

因此游戏中有手榴弹(显然会爆炸并造成伤害),这种爆炸被视为“爆炸效应”。手榴弹所在的方形在运行时可能会出现电力故障(PowerfailureEffect)。 ExplosionEffect和PowerfailureEffect可以耦合,这会导致爆炸更强烈并造成更多伤害。 ExplosionEffect还可以与其他效果相结合,导致爆炸伤害的行为更加不同

4 个答案:

答案 0 :(得分:2)

您可以使用访客设计模式。 所有效果类都实现了一个Effect接口。 Main类使用Effect接口方法询问EffectB类应该如何表现。 在EffectB类中实现Effect方法在主类中调用正确的方法。

答案 1 :(得分:1)

另一个界面怎么样?也许有效果实现的各种Modifier接口。这些修饰符可以执行“increaseExplosivePower”之类的操作。您可以instanceof查看该类是否实现了修饰符,然后一个效果可以修改另一个效果。

注意:在接口上执行instanceof是完全可以接受的 - 如果它可以基于它的内容而不是基于它具有哪些API来执行某些操作,那么就无法解决这个问题。

答案 2 :(得分:0)

public void test(){
    methodForWaterEffect(new WaterEffect());
    combinationAttack1(new FireEffect(), new WaterEffect());
}

interface Effect{
    public void activateEffect();
}

class FireEffect implements Effect{

    @Override
    public void activateEffect() {
        System.out.println("Fire!");
    }

}

class WaterEffect implements Effect{

    @Override
    public void activateEffect() {
        System.out.println("Water!");
    }

}
public void combinationAttack1(FireEffect fe, WaterEffect we){
    //your algorithm here

}

public void methodForWaterEffect(WaterEffect fe){
    fe.activateEffect();
}

我有一个非常简单的建议。为什么不为实现名为Effect的接口的每个效果创建类。此外,如果您正在尝试模拟组合攻击,为什么不为每个组合攻击创建函数?

所以在你的例子中,它将是

public void combination2(PoisonEffect pe, PowerFailureEffect pf){

}

这可能看起来很重要,但我认为这会很好地解耦您的代码,以后您可能会发现管理代码更容易。

请注意,为简单起见,它们不在单独的类文件中= D.

答案 3 :(得分:-1)

常见的反模式是使用类型检查,例如使用instanceof,而不是多态。这是一个简单的例子。

public class Shape {
    public void draw() {
        if (this instanceof Square) {
            // Draw a square
        } else if (this instanceof Circle) {
            // Draw a circle
        }
    }
}

public class Square extends Shape {
    // ...
}

public class Circle extends Shape {
    // ...
}

请注意,在类draw()中的Shape方法中,我们通过查看当前对象的类型,然后执行适当的代码来确定要绘制的内容。这有几个缺点:类Shape需要知道它的所有子类,如果你想添加一个新的形状,你也必须修改类Shape。通过覆盖子类中的draw()方法来使用多态更好:

public abstract class Shape {
    public abstract void draw();
}

public class Square extends Shape {
    public void draw() {
        // Draw a square
    }
}

public class Circle extends Shape {
    public void draw() {
        // Draw a circle
    }
}

这样,类Shape不需要知道它的所有子类,你不需要修改Shape来添加新形状,所有属于特定形状的逻辑都是在它所属的地方(该形状的类)。