java - 如何改进我的代码设计以消除 Java 中对“instanceof”的需求?
问题描述
我决定尝试创建一个简单的游戏引擎,但我似乎被困在如何检查我的游戏对象的不同 Collider 类型之间的碰撞而不需要重复使用“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...
}
}
我想知道是否有更好的方法来做到这一点,主要有两个原因:
- 我听说使用“instanceof”关键字以这种方式检查对象类型是不良代码设计的一种解决方法
- 将来添加自定义 Collider 类型将需要我在此处以及在我的 Collider 类中扩展逻辑
解决方案
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
。为了减少这种分裂的影响,在需要的地方和不需要的地方之间划分类型。
推荐阅读
- excel - 将值从一个 Excel 文件复制到另一个
- julia - 多个返回值的类型注释签名
- javascript - 将属性添加到数据表中的多个
- android - 位置 1024 的 JSON 中的意外令牌反应本机
- r - 在 ggplot2 中:1 个图中 3 个不同数据集的列的总和
- python - 创建比例数据框
- java - 在 VS Code 中启动现有的 Java 程序
- tensorflow - ValueError:传递的张量应该具有等于当前图的图属性
- css - 响应式 SVG 背景 / tailwindcss
- javascript - 主题开发:从 functions.php 链接时 JavaScript 不工作