模拟中“动态”对象的结构

时间:2017-07-07 21:46:27

标签: java data-structures game-physics simulator

我想创建一个或多或少简单的重力模拟,我现在正在做一些关于结构的决定。我遇到过一个问题,我不知道怎么解决“很好”。这是一个简单的问题类图:

The Problem

初看起来你可能看不出任何问题,但是让我告诉你一个额外的事实:如果一颗星达到一定的密度(Schwarzschildradius> Radius),它应该形成一个BlackHole。那么我如何告诉Simulation将Star实例与BlackHole实例交换?我可以为每个主体添加一个Simulation实例,然后他们自己可以修改主体数组,但必须有更好的方法!

另一种方法可能是,让Planet,Star和BlackHole成为新类BodyType的子类,然后Body将持有一个实例。

你怎么看?你会如何以一种干净整洁的方式解决这个问题?任何帮助表示赞赏!

修改:为了进一步说明,我提到的两种方法都是here is an illustration。哪两个更好?还是有一个我没有提到的更好的?

1 个答案:

答案 0 :(得分:0)

也许这可能会有所帮助;在运行时改变行为的一种常用方法是策略模式;我们的想法是保持Body类中所有体型的共同点,并将不同的行为分离到不同的策略中,这样只要身体改变类型,策略就可以交换。而不是BlackHole,Planet和Star扩展Body,他们可以实现一个接口,比如BodyBehavior;

public interface BodyBehaviour {
    String getType ();
    Double getLuminosity (Body body);
    // anything else you need that's type specific....
}

public class PlanetBodyBehavior implements BodyBehaviour {
    public static final String TYPE = "Planet"
    @Override
    public String getType() {
        return TYPE;
    }

    @Override
    public Double getLuminosity(Body body) {
        // planet specific luminosity calculation - probably 0 
        return calculatedLuminosity;
    }
}

你的身体类看起来像;

public class Body {
    private Double mass;

    // coordinates,radius and other state variables

    private BodyBehavior bodyBehaviour;

    public void setBodyBehaviour (BodyBehaviour behaviour) {
        this.bodyBehaviour = behaviour;
    }

    public String getBodyType () {
        bodyBehaviour.getType();
    }

    public Double getLuminosity () {
        bodyBehavior.getLuminosity(this);
    }
}

对于你的模拟你可以有类似的东西;

// init - note we keep our behaviors stateless so we only need one instance of each
public class Simulation () {
    BodyBehaviour planetBehavior = new PlanetBodyBehavior();
    BodyBehaviour starBehavior = new StarBodyBehavior()
    BodyBehaviour blackHoleBehavior = new BlackHoleBodyBehavior()
    // Just showing initialisation for a single star...
    Body body = new Body(initilising params....)
    body.setBehaviour (starBehavior);

        // iterations....
    while (!finished) {
        // assume we have many bodies and loop over them
        for (Body body : allBodies) {
            // update body positions etc.
            // check it's still a star - don't want to be changing it every iteration...
            if (body.hasBecomeBlackHole() {
                // and this is the point of it all....
                body.setBodyBehaviour(blackHoleBehavior);
            }
        }
    }
}

快乐模拟!

请注意,在这种情况下,它是调用行为更改的顶级模拟循环,但您可以将其添加到BodyBehavior中;

boolean hasBecomeBlackHole (Body body);

在体内你可以做类似

的事情
public boolean hasBecomeBlackHole () {
    bodyBehaviour.hasBecomeBlackHole(this);
}

对于StarBodyBehavior;

public boolean hasBecomeBlackHole (final Body body) {
    return doSomeCalculations(body.getMass(), body.getRadius());
}

对于行星和黑洞

public boolean hasBecomeBlackHole (final Body body) {
    return false;
}