簡體   English   中英

如何改進我的代碼設計以消除 Java 中對“instanceof”的需求?

[英]How can I improve my code design to remove the need for 'instanceof' in Java?

我決定嘗試創建一個簡單的游戲引擎,但我似乎被困在如何為我的游戲對象檢查不同碰撞器類型之間的碰撞而無需重復使用“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...
    }
}

Collider3D 類

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);

}

AABBCollider3D 類

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

}

我想知道是否有更好的方法來做到這一點,主要有兩個原因:

  1. 我聽說使用 'instanceof' 關鍵字以這種方式檢查對象類型是錯誤代碼設計的一種解決方法
  2. 將來添加自定義碰撞器類型將需要我在此處以及我的碰撞器類中擴展邏輯

為每個特殊的子類型在Collider類型中添加一個方法。 這是一種退化的訪問者模式。

所以它看起來像:

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子類型之間創建相互依賴關系。 為了減少這種分裂的影響,在需要的地方和不需要的地方之間划分類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM