模拟中 "dynamic" objects 的结构
Structure for "dynamic" objects in a simulation
我想创建一个或多或少简单的重力模拟,我目前正在对结构做出一些决定。我遇到了一个问题,我不知道如何解决"nicely"。这是问题的简单 class 图:
乍一看你可能看不出任何问题,但让我告诉你一个额外的事实:如果一颗恒星达到一定的密度(Schwarzschildadius > Radius),它应该形成一个黑洞。那么我如何告诉模拟将 Star 实例与 BlackHole 实例交换呢?我可以为每个 body 添加一个 Simulation 实例,然后他们自己可以修改 bodys 数组,但必须有更好的方法!
另一种方法可能是,让 Planet、Star 和 BlackHole 成为新 class Body 类型的子class,然后 Body持有一个实例。
你怎么看?你会如何以一种干净利落的方式解决这个问题?感谢您的帮助!
编辑:为了进一步说明,here is an illustration 我提到的两种方法。两者哪个更好?或者有没有更好的我没有提到的?
也许这会有所帮助;在运行时改变行为的一种常用方法是策略模式;这个想法是让 Body class 中的所有 body 类型都通用,并将不同的行为分离到不同的策略中,这样就可以在 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;
}
}
你的 body class 看起来像;
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);
在body中你可以做类似
的事情
public boolean hasBecomeBlackHole () {
bodyBehaviour.hasBecomeBlackHole(this);
}
为明星Body行为;
public boolean hasBecomeBlackHole (final Body body) {
return doSomeCalculations(body.getMass(), body.getRadius());
}
对于行星和黑洞
public boolean hasBecomeBlackHole (final Body body) {
return false;
}
我想创建一个或多或少简单的重力模拟,我目前正在对结构做出一些决定。我遇到了一个问题,我不知道如何解决"nicely"。这是问题的简单 class 图:
乍一看你可能看不出任何问题,但让我告诉你一个额外的事实:如果一颗恒星达到一定的密度(Schwarzschildadius > Radius),它应该形成一个黑洞。那么我如何告诉模拟将 Star 实例与 BlackHole 实例交换呢?我可以为每个 body 添加一个 Simulation 实例,然后他们自己可以修改 bodys 数组,但必须有更好的方法!
另一种方法可能是,让 Planet、Star 和 BlackHole 成为新 class Body 类型的子class,然后 Body持有一个实例。
你怎么看?你会如何以一种干净利落的方式解决这个问题?感谢您的帮助!
编辑:为了进一步说明,here is an illustration 我提到的两种方法。两者哪个更好?或者有没有更好的我没有提到的?
也许这会有所帮助;在运行时改变行为的一种常用方法是策略模式;这个想法是让 Body class 中的所有 body 类型都通用,并将不同的行为分离到不同的策略中,这样就可以在 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;
}
}
你的 body class 看起来像;
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);
在body中你可以做类似
的事情public boolean hasBecomeBlackHole () {
bodyBehaviour.hasBecomeBlackHole(this);
}
为明星Body行为;
public boolean hasBecomeBlackHole (final Body body) {
return doSomeCalculations(body.getMass(), body.getRadius());
}
对于行星和黑洞
public boolean hasBecomeBlackHole (final Body body) {
return false;
}