You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于UML接口与抽象类聚合的太阳系模拟Applet实现技术问询

嘿,既然你已经搞定了太阳系Applet的动画效果,那离满分就差把代码对齐指定UML规范这一步啦!我来帮你梳理下怎么精准实现这个层级结构:

核心UML结构对应实现拆解

1. 先明确接口与类的层级关系

按照你提到的UML要求,核心约束是:

  • Sun必须实现Orbit接口,同时作为顶层天体,持有通过Planet构造函数创建的OrbitingBody实例(也就是行星)
  • Planet作为OrbitingBody的子类/实现类,自身也要持有通过卫星构造函数创建的OrbitingBody实例(比如Moon)
  • 所有参与轨道运动的天体(Sun、Planet、Moon)都要遵循Orbit接口的规范

2. 代码实现的关键步骤

第一步:定义Orbit接口

先把接口的核心方法定下来,确保所有天体都遵循统一的动画逻辑规范:

public interface Orbit {
    // 每帧更新位置(轨道运动计算)
    void update(long deltaTime);
    // 绘制自身及下属天体
    void draw(Graphics g);
}

第二步:实现Sun类

Sun作为中心天体,实现Orbit接口,同时管理所有行星:

import java.util.ArrayList;
import java.util.List;
import java.awt.*;

public class Sun implements Orbit {
    private List<OrbitingBody> planets;
    private int centerX, centerY;
    private final int SIZE = 40;

    public Sun(int x, int y) {
        this.centerX = x;
        this.centerY = y;
        planets = new ArrayList<>();
        // 通过Planet构造函数添加行星,比如地球
        planets.add(new Planet(this, 120, 0.002));
    }

    @Override
    public void update(long deltaTime) {
        // 太阳自身固定不动,只更新所有行星的位置
        for (OrbitingBody planet : planets) {
            planet.update(deltaTime);
        }
    }

    @Override
    public void draw(Graphics g) {
        // 绘制太阳
        g.setColor(Color.YELLOW);
        g.fillOval(centerX - SIZE/2, centerY - SIZE/2, SIZE, SIZE);
        // 绘制所有行星及其卫星
        for (OrbitingBody planet : planets) {
            planet.draw(g);
        }
    }

    // 提供给行星获取太阳位置的方法
    public int getCenterX() { return centerX; }
    public int getCenterY() { return centerY; }
}

第三步:抽象OrbitingBody类

这个类作为行星和卫星的父类,封装通用的轨道运动逻辑,避免重复代码:

import java.awt.*;

public abstract class OrbitingBody implements Orbit {
    protected Orbit parentBody;
    protected int orbitRadius;
    protected double currentAngle;
    protected double orbitSpeed;
    protected int currentX, currentY;

    public OrbitingBody(Orbit parent, int radius, double speed) {
        this.parentBody = parent;
        this.orbitRadius = radius;
        this.orbitSpeed = speed;
        this.currentAngle = 0;
    }

    @Override
    public void update(long deltaTime) {
        // 计算当前轨道角度
        currentAngle += orbitSpeed * deltaTime;
        // 根据父天体位置计算自身坐标
        Point parentPos = getParentPosition();
        currentX = parentPos.x + (int)(Math.cos(currentAngle) * orbitRadius);
        currentY = parentPos.y + (int)(Math.sin(currentAngle) * orbitRadius);
        // 更新下属天体(比如行星的卫星)
        updateChildBodies(deltaTime);
    }

    // 子类必须实现的方法:获取父天体的位置
    protected abstract Point getParentPosition();
    // 子类实现:更新自己的子天体
    protected abstract void updateChildBodies(long deltaTime);
}

第四步:实现Planet类

Planet继承OrbitingBody,同时管理自己的卫星:

import java.util.ArrayList;
import java.util.List;
import java.awt.*;

public class Planet extends OrbitingBody {
    private List<OrbitingBody> moons;
    private final int SIZE = 20;
    private Color planetColor;

    public Planet(Orbit parent, int radius, double speed) {
        super(parent, radius, speed);
        moons = new ArrayList<>();
        this.planetColor = Color.BLUE;
        // 通过Moon构造函数添加卫星,比如月球
        moons.add(new Moon(this, 30, 0.005));
    }

    @Override
    protected Point getParentPosition() {
        // 父天体是Sun,获取太阳的中心坐标
        if (parentBody instanceof Sun) {
            Sun sun = (Sun) parentBody;
            return new Point(sun.getCenterX(), sun.getCenterY());
        }
        return new Point(0, 0);
    }

    @Override
    protected void updateChildBodies(long deltaTime) {
        for (OrbitingBody moon : moons) {
            moon.update(deltaTime);
        }
    }

    @Override
    public void draw(Graphics g) {
        // 绘制行星
        g.setColor(planetColor);
        g.fillOval(currentX - SIZE/2, currentY - SIZE/2, SIZE, SIZE);
        // 绘制所有卫星
        for (OrbitingBody moon : moons) {
            moon.draw(g);
        }
    }

    // 提供给卫星获取行星位置的方法
    public int getCurrentX() { return currentX; }
    public int getCurrentY() { return currentY; }
}

第五步:实现Moon类

Moon继承OrbitingBody,作为最底层的天体:

import java.awt.*;

public class Moon extends OrbitingBody {
    private final int SIZE = 10;

    public Moon(Orbit parent, int radius, double speed) {
        super(parent, radius, speed);
    }

    @Override
    protected Point getParentPosition() {
        // 父天体是Planet,获取行星的当前坐标
        if (parentBody instanceof Planet) {
            Planet planet = (Planet) parentBody;
            return new Point(planet.getCurrentX(), planet.getCurrentY());
        }
        return new Point(0, 0);
    }

    @Override
    protected void updateChildBodies(long deltaTime) {
        // 月球没有下属天体,空实现即可
    }

    @Override
    public void draw(Graphics g) {
        // 绘制月球
        g.setColor(Color.GRAY);
        g.fillOval(currentX - SIZE/2, currentY - SIZE/2, SIZE, SIZE);
    }
}

3. 最后调整适配你的Applet

把这些类整合到你的Applet中,在paint()或者run()方法里调用Sun的update()和draw()方法就行,比如:

import java.applet.Applet;
import java.awt.*;

public class SolarSystemApplet extends Applet implements Runnable {
    private Sun sun;
    private Thread animationThread;

    @Override
    public void init() {
        sun = new Sun(getWidth()/2, getHeight()/2);
        animationThread = new Thread(this);
        animationThread.start();
    }

    @Override
    public void run() {
        long lastTime = System.currentTimeMillis();
        while (true) {
            long currentTime = System.currentTimeMillis();
            long deltaTime = currentTime - lastTime;
            sun.update(deltaTime);
            repaint();
            lastTime = currentTime;
            try {
                Thread.sleep(16); // 约60帧每秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void paint(Graphics g) {
        sun.draw(g);
    }
}
小提示
  • 如果UML里有特定的方法名、成员变量或者访问修饰符要求,直接对应调整上面的代码就行
  • 轨道运动的速度、半径这些参数可以根据你的动画效果微调,确保行星和卫星的运动节奏合理
  • 可以给不同行星设置不同的颜色、大小,让太阳系更逼真

内容的提问来源于stack exchange,提问作者Diego Rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:13:27