Java:我如何让球像弹跳和弹性球一样?

时间:2016-02-02 09:16:35

标签: java

我有两个班BouncingBall,另一个班叫ElasticBall。这两个类都扩展了BallImpl,它实现了一个名为Ball的接口。

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;
    }
}

我需要创建一个BouncingElasticBall,它结合了BouncingBallElasticBall类的行为。我对OOP知之甚少,而且我知道Java不允许多重继承,那么我该如何解决这个问题?

提前致谢。

3 个答案:

答案 0 :(得分:6)

您可以采用的一种方法是不扩展 BallImpl,而是制作排序插件。像这样:

public class BallImpl implements Ball {
    List<BallBehavior> behaviors = ...

    @Override
    public void update() {
       behaviors.forEach(behavior -> behavior.update(this));
    }
    ...
}

public interface BallBehavior {
    void update(BallImpl ballImpl);
}

然后,只需将弹性和弹跳逻辑写为行为

答案 1 :(得分:2)

一旦你将层次结构分开,就无法在java中合并它们。

设计问题:如果您知道可以将ElasticBallBouncingBall组合在一起,则应创建两个接口ElasticBouncing,两者均可扩展接口Ball,常用方法对两者都有效。

然后可以将常用方法实现设置为公共抽象类,让我们说AbstractBall。此时,您最终可以详细说明您的三个实现:

  • ElasticBall extends AbstractBall implements Elastic
  • BouncingBall extendis AbstractBall implements Bouncing
  • ElasticBouncingBall extends AbstractBall implements Elastic, Bouncing

通过这种方式,您将能够控制每个方法中的操作,重用常见内容的代码(在抽象类中)。

答案 2 :(得分:1)

您可以使用允许多重继承的接口。为每个球ElasticBallBouncingBall创建界面,并在BouncingElasticBall中实现这两个界面。