Java 如何改进代码设计以消除对';instanceof';在爪哇?

Java 如何改进代码设计以消除对';instanceof';在爪哇?,java,oop,reflection,Java,Oop,Reflection,我决定尝试创建一个简单的游戏引擎,我似乎被困在如何检查我的游戏对象的不同碰撞器类型之间的碰撞,而不需要重复使用“instanceof”。例如,某些游戏对象可能使用SphereCollider,而其他对象可能使用AABBCollider,两者都扩展了Collider类 下面是我的GameObject类中的代码 public final boolean collidesWith(Collider c) { if (this.collider instanceof Collider3D) {

我决定尝试创建一个简单的游戏引擎,我似乎被困在如何检查我的游戏对象的不同碰撞器类型之间的碰撞,而不需要重复使用“instanceof”。例如,某些游戏对象可能使用SphereCollider,而其他对象可能使用AABBCollider,两者都扩展了Collider类

下面是我的GameObject类中的代码

public final boolean collidesWith(Collider c) {
    if (this.collider instanceof Collider3D) {
        if (c instanceof AABBCollider3D) {
            if (((Collider3D) this.collider).collidesWith((AABBCollider3D) c))
                return true;
        } else if (c instanceof SphereCollider3D) {
            if (((Collider3D) this.collider).collidesWith((SphereCollider3D) c))
                return true;
        } else if (c instanceof AABBCollider2D) {
            if (((Collider3D) this.collider).intersects((AABBCollider2D) c))
                return true;
        }
    } else if (this.collider instanceof Collider2D) {
        // Do 2D collision stuff...
    }
}
碰撞类

public abstract class Collider3D extends Collider {

public Collider3D(RigidBody rigidBody) {
    super(rigidBody);
}


public abstract boolean collidesWith(AABBCollider3D collider);

public abstract boolean collidesWith(SphereCollider3D collider);

public abstract boolean intersects(AABBCollider2D collider);

public abstract boolean intersects(CircleCollider2D collider);

}
public class AABBCollider3D extends Collider3D {

private final Cuboid collisionBounds;


public AABBCollider3D(RigidBody rigidBody) {
    super(rigidBody);

    this.collisionBounds = new Cuboid();
}


@Override
public void update() {
    final Vector3f objectLocation = getRigidBody().getObject().getLocation().getPosition();
    final Matrix4f transformMatrix = getRigidBody().getObject().getTransformationMatrix();

    final float width = transformMatrix.m03();
    final float height = transformMatrix.m13();
    final float depth = transformMatrix.m23();

    // Set the collision bounds' location
    collisionBounds.getLocation().setPosition(
            objectLocation.x,
            objectLocation.y,
            objectLocation.z);  

    // Set the dimension of the collision bounds
    collisionBounds.setWidth(width);
    collisionBounds.setHeight(height);
    collisionBounds.setDepth(depth);
}

@Override
public boolean collidesWith(AABBCollider3D collider) {
    // Check collisions...
}

@Override
public boolean collidesWith(SphereCollider3D collider) {
    // Check collisions...
}

@Override
public boolean intersects(AABBCollider2D collider) {
    // Check collisions...
}

@Override
public boolean intersects(CircleCollider2D collider) {
    // Check collisions...
}

}
aabbr3d类

public abstract class Collider3D extends Collider {

public Collider3D(RigidBody rigidBody) {
    super(rigidBody);
}


public abstract boolean collidesWith(AABBCollider3D collider);

public abstract boolean collidesWith(SphereCollider3D collider);

public abstract boolean intersects(AABBCollider2D collider);

public abstract boolean intersects(CircleCollider2D collider);

}
public class AABBCollider3D extends Collider3D {

private final Cuboid collisionBounds;


public AABBCollider3D(RigidBody rigidBody) {
    super(rigidBody);

    this.collisionBounds = new Cuboid();
}


@Override
public void update() {
    final Vector3f objectLocation = getRigidBody().getObject().getLocation().getPosition();
    final Matrix4f transformMatrix = getRigidBody().getObject().getTransformationMatrix();

    final float width = transformMatrix.m03();
    final float height = transformMatrix.m13();
    final float depth = transformMatrix.m23();

    // Set the collision bounds' location
    collisionBounds.getLocation().setPosition(
            objectLocation.x,
            objectLocation.y,
            objectLocation.z);  

    // Set the dimension of the collision bounds
    collisionBounds.setWidth(width);
    collisionBounds.setHeight(height);
    collisionBounds.setDepth(depth);
}

@Override
public boolean collidesWith(AABBCollider3D collider) {
    // Check collisions...
}

@Override
public boolean collidesWith(SphereCollider3D collider) {
    // Check collisions...
}

@Override
public boolean intersects(AABBCollider2D collider) {
    // Check collisions...
}

@Override
public boolean intersects(CircleCollider2D collider) {
    // Check collisions...
}

}
我想知道是否有更好的方法,主要有两个原因:

  • 我听说用'instanceof'关键字来检查对象类型是一种解决糟糕代码设计的方法
  • 将来添加自定义碰撞器类型需要我在这里以及在碰撞器类中扩展逻辑

  • 为每个特殊子类型在碰撞器中添加方法。这是一种退化的访问者模式

    所以它看起来像:

    interface Collider {
        boolean collidesWith(Collider other);
    
        // I've used the same name here,
        //   not necessary but makes things easier.
        boolean collidedBy(AABBCollider3D collider);
        boolean collidedBy(SphereCollider3D collider);
        // ...
    }
    
    每个子类型将类似于:

    public class AABBCollider3D implements Collider {
        public boolean collidesWith(Collider other) {
            return other.collidedBy(this);
        }
    
        public boolean collidedBy(AABBCollider3D collider) {
            // ... code for AABBCollider3D collided by AABBCollider3D.
        }
        public boolean collidedBy(SphereCollider3D collider) {
            // ... code for AABBCollider3D collided by SphereCollider3D.
        }
        // ...
    }
    

    这将在
    碰撞器
    子类型之间创建相互依赖关系。为了减少此操作的影响,请将类型在需要和不需要之间进行拆分。

    您在哪里使用反射?您是否编写了
    碰撞器
    类?如果
    Collider
    设计得很好,就不需要强制转换。是的,我编写了Collider类,但我对编程相当陌生,所以我可能没有以最好的方式完成它。目前,我在基类中为每种不同类型的对撞机提供了抽象方法来进行检查。有更好的方法吗?是的,你能展示
    碰撞器
    类和碰撞器的2个子类吗?我还没有编写逻辑来实际检查每个碰撞器的碰撞,但我将展示碰撞器类和AABBCollider3D类作为一个例子。基本的Collider类目前是空的,所以我不会显示它。对不起,我对编程非常陌生,我不太清楚你的意思。它是否与我展示的Collider3D类相似,我在其中为我希望检查的每个Collider子类提供了一个抽象方法?