也許這可能有幫助;在運行時改變行爲的一種常見方法是戰略模式;其思想是保持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;
}
非常有趣的模式,我喜歡它!但我仍然有一個問題。由於BodyBehaviour實現了類型特定的代碼,因此它還需要決定何時更改爲新的BodyBehaviour。所以它仍然需要對Body的引用,對吧? –
請聽你喜歡它!我已經編輯過希望澄清和封裝star-> bh轉換的測試。您正確的是我們將自引用(this)傳遞給策略方法,但是它是BodyBehavior的引用的主體,而不是另一種方式。由於策略是無狀態的(沒有成員變量),我們只需要每種類型的一個實例,而不管模擬中有多少個實體。希望有所幫助! – GrumpyWelshGit
我想我會採用這種方法,稍作修改:而不是特定的hasBecomeBlackHole()函數,我將使用更通用的needsTransition()函數和第二個轉換(Body body)函數。這樣我可以實現多個可能的轉換而不需要幾十個函數。所以在Body類中它會檢查每個更新是否需要轉換,如果是,它將通過轉換(Body body)傳遞其引用,以便BodyBehaviour可以完成必要的工作。或者第二個函數可以返回BodyBehaviour,以便Body更改它。 –