我想创建一个或多或少简单的重力模拟,我现在正在做一些关于结构的决定。我遇到过一个问题,我不知道怎么解决“很好”。这是一个简单的问题类图:
初看起来你可能看不出任何问题,但是让我告诉你一个额外的事实:如果一颗星达到一定的密度(Schwarzschildradius> Radius),它应该形成一个BlackHole。那么我如何告诉Simulation将Star实例与BlackHole实例交换?我可以为每个主体添加一个Simulation实例,然后他们自己可以修改主体数组,但必须有更好的方法!
另一种方法可能是,让Planet,Star和BlackHole成为新类BodyType的子类,然后Body将持有一个实例。
你怎么看?你会如何以一种干净整洁的方式解决这个问题?任何帮助表示赞赏!修改:为了进一步说明,我提到的两种方法都是here is an illustration。哪两个更好?还是有一个我没有提到的更好的?
答案 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;
}