避免在组合模式中使用 instanceof

5
我正在为大学的一个项目编写游戏程序。在这个游戏中,会发生几种效果,其中一种效果会影响另一种效果的行为。现在有一个想法是使用组合模式,起初似乎是一个很好的解决方案。最大的问题在于,一个效果的行为方式取决于它与哪个效果相结合,我们唯一看到的解决方法是使用.getClass()或instanceof,但我们要尽量避免使用这些方法。
有哪些方法可以解决这个问题?
编辑(一个小例子):我没有明确的代码示例,但我将用以下示例来澄清一下:
所以游戏中有手榴弹(显然可以爆炸并造成伤害),这个爆炸被视为“ExplosionEffect”。手榴弹所在的正方形可能会在运行时出现电力故障(PowerfailureEffect)。ExplosionEffect和PowerfailureEffect可以耦合在一起,这会导致爆炸更强,并造成更多的伤害。ExplosionEffect还可以与其他效果相结合,使爆炸伤害的行为变得更加不同。

4
提供代码示例会更容易回答你的问题。 - Duncan Jones
4个回答

2
您可以使用访问者设计模式。 所有效果类都实现了一个Effect接口。 主类通过使用Effect接口方法询问EffectB类应如何行动。 EffectB类中Effect方法的实现调用了主类中正确的方法。

1
如何使用另一个接口?也许可以有各种效果实现的Modifier接口。这些修改器可以执行诸如“增加爆炸力”之类的操作。您可以使用instanceof来查看类是否实现了修改器,然后一个效果可以修改另一个效果。
注意:在接口上执行instanceof是完全可接受的-您不是根据它是什么来确定它能否执行某些操作,而是根据其API。

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。


-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 {
    // ...
}

请注意,在类Shapedraw()方法中,我们通过查看当前对象的类型并执行适当的代码来确定要绘制什么。这有几个缺点:类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以添加新形状,并且属于特定形状的所有逻辑都在其所属的位置(即该形状的类)中。

我没有点踩,但我认为点踩者没有完整地阅读你的答案。你的回答的前半部分似乎暗示了你建议使用instanceof,而后半部分则解释了其缺点以及多态作为替代方案。然而,我认为提供一些如何将其应用于组合模式的上下文会让这个答案更加深入。 - seanhodges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接