Java 爪哇:我怎样才能使一个球表现得像一个弹跳的弹性球?

Java 爪哇:我怎样才能使一个球表现得像一个弹跳的弹性球?,java,Java,我有两门课BouncingBall,还有一门叫做ElasticBall。这两个类都扩展了实现名为Ball的接口的BallImpl public interface Ball { int DEFAULT_RADIUS = 50; int radius(); Point center(); void update(); } public class BouncingBall extends BallImpl { public static final in

我有两门课
BouncingBall
,还有一门叫做
ElasticBall
。这两个类都扩展了实现名为
Ball
的接口的
BallImpl

public interface Ball {
    int DEFAULT_RADIUS = 50;

    int radius();
    Point center();
    void update();
}

public class BouncingBall extends BallImpl {
    public static final int MOVEMENT_SPEED = 12;

    static final int DOWN = 1;
    static final int UP = -1;

    private int direction;

    BouncingBall(int x, int y, int direction) {
        super(x, y);
        this.direction = direction;
    }

    @Override
    public void update() {
        direction = reverseDirectionIfNecessary();
        y = move();
    }

    private int reverseDirectionIfNecessary() {
        if (movingTooHigh() || movingTooLow()) {
            return switchDirection();
        }

        return this.direction;
    }

    private boolean movingTooLow() {
        return y + radius >= BallWorld.BOX_HEIGHT && movingDown();
    }

    private boolean movingTooHigh() {
        return y - radius <= 0 && movingUp();
    }

    private int switchDirection() {
        return movingDown() ? UP : DOWN;
    }

    private int move() {
        return y + (MOVEMENT_SPEED * direction);
    }

    private boolean movingDown() {
        return direction == DOWN;
    }

    private boolean movingUp() {
        return direction == UP;
    }
}

public class ElasticBall extends BallImpl {
    public static final int GROWTH_RATE = 2;

    static final int GROW = 1;
    static final int SHRINK = -1;

    private int growthDirection;

    ElasticBall(int x, int y, int radius, int growthDirection) {
        super(x, y, radius);
        this.growthDirection = growthDirection;
    }

    @Override
    public void update() {
        growthDirection = reverseGrowthDirectionIfNecessary();
        radius = next();
    }

    private int reverseGrowthDirectionIfNecessary() {
        if (growingTooBig() || shrinkingTooSmall()) {
            return switchDirection();
        }

        return this.growthDirection;
    }

    private boolean shrinkingTooSmall() {
        return radius <= 0 && shrinking();
    }

    private boolean growingTooBig() {
        return radius >= Ball.DEFAULT_RADIUS && growing();
    }

    private int switchDirection() {
        return growing() ? SHRINK : GROW;
    }

    private int next() {
        return radius + (GROWTH_RATE * growthDirection);
    }

    private boolean shrinking() {
        return growthDirection == SHRINK;
    }

    private boolean growing() {
        return growthDirection == GROW;
    }
}
公共接口球{
int默认_半径=50;
int半径();
点中心();
无效更新();
}
公共类弹跳球扩展BallImpl{
公共静态最终整数移动速度=12;
静态最终整数向下=1;
静态最终整型=-1;
私人int方向;
弹跳球(整数x,整数y,整数方向){
super(x,y);
这个方向=方向;
}
@凌驾
公共无效更新(){
方向=反转方向(如有必要)();
y=移动();
}
私有int reverseDirectionIfEssential(){
if(movingTooHigh()| | movingTooLow()){
返回开关方向();
}
返回这个方向;
}
私有布尔movingTooLow(){
返回y+半径>=BallWorld.BOX_高度和向下移动();
}
私有布尔值movingTooHigh(){

返回y-radius一旦您分离了层次结构,就无法在java中合并它们

这是一个设计问题:如果您知道
ElasticBall
BouncingBall
可以组合在一起,那么您应该创建两个接口
Elastic
Bouncing
,这两个接口都是扩展接口
Ball
,使用对这两个接口都有效的常用方法

然后,可以将公共方法实现设置为一个公共抽象类,比如说
AbstractBall
。在这一点上,您最终可以详细介绍三个实现:

  • ElasticBall扩展了AbstractBall实现了弹性
  • BouncingBall extendis AbstractBall实现反弹
  • ElasticBouncingBall扩展AbstractBall实现弹性反弹

通过这种方式,您将能够控制在每个方法中要做什么,重用代码来处理常见的内容(在抽象类中)

public interface Ball {
    int DEFAULT_RADIUS = 50;

    int radius();
    Point center();
    void update();
}

public class BouncingBall extends BallImpl {
    public static final int MOVEMENT_SPEED = 12;

    static final int DOWN = 1;
    static final int UP = -1;

    private int direction;

    BouncingBall(int x, int y, int direction) {
        super(x, y);
        this.direction = direction;
    }

    @Override
    public void update() {
        direction = reverseDirectionIfNecessary();
        y = move();
    }

    private int reverseDirectionIfNecessary() {
        if (movingTooHigh() || movingTooLow()) {
            return switchDirection();
        }

        return this.direction;
    }

    private boolean movingTooLow() {
        return y + radius >= BallWorld.BOX_HEIGHT && movingDown();
    }

    private boolean movingTooHigh() {
        return y - radius <= 0 && movingUp();
    }

    private int switchDirection() {
        return movingDown() ? UP : DOWN;
    }

    private int move() {
        return y + (MOVEMENT_SPEED * direction);
    }

    private boolean movingDown() {
        return direction == DOWN;
    }

    private boolean movingUp() {
        return direction == UP;
    }
}

public class ElasticBall extends BallImpl {
    public static final int GROWTH_RATE = 2;

    static final int GROW = 1;
    static final int SHRINK = -1;

    private int growthDirection;

    ElasticBall(int x, int y, int radius, int growthDirection) {
        super(x, y, radius);
        this.growthDirection = growthDirection;
    }

    @Override
    public void update() {
        growthDirection = reverseGrowthDirectionIfNecessary();
        radius = next();
    }

    private int reverseGrowthDirectionIfNecessary() {
        if (growingTooBig() || shrinkingTooSmall()) {
            return switchDirection();
        }

        return this.growthDirection;
    }

    private boolean shrinkingTooSmall() {
        return radius <= 0 && shrinking();
    }

    private boolean growingTooBig() {
        return radius >= Ball.DEFAULT_RADIUS && growing();
    }

    private int switchDirection() {
        return growing() ? SHRINK : GROW;
    }

    private int next() {
        return radius + (GROWTH_RATE * growthDirection);
    }

    private boolean shrinking() {
        return growthDirection == SHRINK;
    }

    private boolean growing() {
        return growthDirection == GROW;
    }
}
公共类BallImpl实现Ball{
列出行为=。。。
@凌驾
公共无效更新(){
behavior.forEach(behavior->behavior.update(this));
}
...
}
公共接口行为{
作废更新(BallImpl BallImpl);
}

然后,把你的弹性和弹跳逻辑写成行为。

你不能从其中一个继承
BouncingElasticBall
,而不必有两个超类吗?为什么你需要它们都分开?从设计的角度来看,你可以有
ElasticBall
BouncingBall
实现
Ball
inteFace而不是扩展一个超类。从物理学的角度来看,我不知道如何立即使球反弹。这种要求很愚蠢。提出解决方案的最好方法是,像往常一样,组合。如果你现在想要一个
重新更新的弹跳球和一个
黄色的弹跳球怎么办?要创建所有的类呢S:直到所有的组合都被覆盖了。不:使用组合。有一个球,你可以重复使用并完成它。告诉任何设计它的人,他/她不理解OOP的概念。它是面向对象的编程,而不是全对象编程。考虑一下你的问题。听起来你是在问物理,但是A。实际上,这实际上是一个“如何进行适当的OO设计”问题。关键在于你的问题:当你想要行为时,你应该立即思考界面。注意:在模式语言中,这被称为访客模式。在我看来,你的答案是解决原始问题的最佳选择。我甚至会创建一个
ComposedBallBehavior
,来完成这个问题r-loop,只允许类中有一个
BallBehavior
,而不允许它们的列表。