Java OOP:如何正确创建对象

时间:2012-05-28 13:34:45

标签: java oop object

我正在使用OOP创建一个简单的保龄球游戏,我希望每个碗都有一个类,一个由两个碗组成的Frame类,以及一个由十个帧组成的Game类。

目前我有这样的事情

Bowl.java

public class Bowl {

int bowlScore = 0;

public Bowl(int pinsKnocked){
    bowlScore = pinsKnocked;
}
}

Frame.java

public class Frame{

int firstScore;
int secondScore;
public Bowl firstBowl;
public Bowl secondBowl;

public Frame (){
    firstBowl = new Bowl(0);
    secondBowl = new Bowl(0);
}

public Frame (int firstScore, int secondScore){
    firstBowl = new Bowl(firstScore);
    secondBowl = new Bowl(secondScore);
} 

Game.java

public class Game {

int totalScore;
public Frame firstFrame;
public Frame secondFrame;
...
    public Frame tenthFrame;

public Game(){
    firstFrame = new Frame();   
}

public Game(Frame f){
    firstFrame = f;
}

这是使用OOP功能的正确方法还是我能如何改进?

3 个答案:

答案 0 :(得分:4)

设计保龄球游戏没有100%正确的方法;有许多解决方案可行,甚至更多不起作用。

您需要的是一个适合您和您的目标的解决方案。

如果您想显示分数,我建议您先使用getScore()方法。如果要显示获奖者,请先使用displayWinners()方法。

最终你会发现这些方法自然地绑定到各种名词。例如,您可以从getScore()附加到Game对象开始,但后来意识到这不自然地意味着您的游戏只能有一个分数。如果发生这种情况,您可以将getScore()移动到Player对象,让游戏维护一个或多个玩家。

如果您正在使用自然属于其他地方的方法,则代码中会有许多提示将指导您。最明显的提示是,一个方法似乎对另一个对象的数据特别感兴趣,甚至对它自己的数据也是如此。在上面的例子中,游戏对象中的getScore()对玩家的框架,球等过于感兴趣。

为了获得如何安全地将代码从一个地方移动到另一个地方的技能和方向,我建议阅读Martin Fowler的重构书。

An excellent example, using exactly your problem is demonstrated here

祝你好运,过了一段时间,由于掌握的技巧,你可以跳过这个过程;但是,在第一次学习时,不要跳过这些探索性步骤(从头开始)是个好主意。

PS。请记住,您的代码只会确定您要测试它做的事情,如果您不熟悉测试驱动开发,那么查看它可能是一个好主意(提示,这是一个巨大的低估)。

答案 1 :(得分:4)

正如埃德温所说,他们有很多方法可以模仿保龄球比赛。但是在这里,我将列出对您的代码进行可能的更正以改进它 这里有很多东西需要改进 1.分数属性仅适用于碗类。所以从Frame和Game中删除得分属性 2. bowlScore中的Bowl应该是私有的,并为其提供getter方法。你会
3.现在Frame类应该是:

public class Frame{
    private Bowl firstBowl;
    private Bowl secondBowl;

    public Frame (int firstScore, int secondScore){
        firstBowl = new Bowl(firstScore);
        secondBowl = new Bowl(secondScore);
    }
    public int getFrameScore(){
       return (firstBowl.getScore()+secondBowl.getScore());
    }
} 

4.在Game类中,你有构造函数,你只传递一帧?一个玩家一个游戏由10个帧组成。对帧使用10个变量也不是一个好主意。为此,我们有java集合。你可以使用列表。

public class Game {
    private java.uti.List<Frame> frames;
    public Game(List<Frame> frames){
      this.frames = frames;
    }
    public getGameScore(){
      // loop goes here to sum up scores from all frames
      //sum = sum+frames.get(i);
    }
}

}

5.如果你假设这个游戏只由一个玩家玩,那么这个建模也是有效的。对于多个玩家,上面的Game类实际上变成了Player类,你将不得不创建新的Game类。

答案 2 :(得分:1)

我倾向于放弃Bowl的多个实例。如果您发现自己处于这种情况,请问自己 - 我将如何处理Bowl的100个实例?考虑在游戏的生命周期中您必须创建和维护的10个Frame实例。除非您需要某些业务逻辑的多个实例,否则保留多个实例并不是一个好主意。

public class Bowl {

    private int bowlScore;

    // Use a no-argument constructor
    public Bowl() {
        this.bowlScore = 0;
    }

    public void setBowlScore( int score ) {
        this.bowlScore = score;
    }

    public int getBowlScore() {
        return this.bowlScore;
    }
}

对于Frame类,

public class Frame {

    private int frameScore;
    private Bowl bowlArray[];

    public Frame() {
        this.frameScore = 0;
        this.bowlArray = new Bowl[2];
    }

    public void setScoreForFirstBowl( int score ) {
        this.bowlArray[0] = score;
        this.frameScore += score;
    }

    public void setScoreForSecondBowl( int score ) {
        this.bowlArray[1] = score;
        this.frameScore += score;
    }

    public void setFrameScore( int score ) {
        this.frameScore = score;
    }

    public int getFrameScore() {
        return this.frameScore;
    }

    // this should not be used, left in for completeness
    public Bowl[] getBowlArray() {
        return this.bowlArray;
    }
}

适用于Game

public class Game {

     private int gameScore;
     private ArrayList<Frame> gameFrames;

     public Game() {
         this.gameScore = 0;
         this.gameFrames = new ArrayList<Frame>();
     }

     /* There are many ways of implementing the game logic. Here is an example.
        You will have to complete the rest :) */

     // @frame frame object with bowl data that is appended to list
     public void frameCompleted(Frame frame) {
         this.gameScore += frame.getFrameScore; // I assume this is what you want to do. Change if not
         this.gameFrames.add(frame);
     }

     /* The method written above can also be implemented by passing integer values
        for the score, bowl number and frame number. However, this would not be very
        OOP friendly. Essentially, this is 'Encapsulation' of the Frame data into the 
        Frame object. */

     // Add getters and setters for gameScore and gameFrames
}

有关进一步使用的示例,请参阅ArrayList文档。如果您不想使用它,可以将其替换为数组。我把它包括在内只是为了展示列表能力。

详情阅读Encapsulation herehere

您会注意到我没有在BowlFrame课程中考虑'罢工'。这是因为这是一个需要照顾的特殊情况,所以我留给你实施。我的理解是,如果你在第一个碗上滚动罢工,你就不会得到第二个碗。