建议在Java中正确使用封装

时间:2010-08-13 08:43:05

标签: java oop encapsulation

我正在创建一个简单的益智游戏,就像一个爱好项目,但该项目现在已达到一个点,即有相当多的代码(大约1500行)。虽然我试图阻止它,但代码变得混乱。我绝对想要清理代码并使其更易于维护和读取,而我仍然可以。

我的游戏中有3个类处理有关拼图的动作:

class PieceController{
    private arrayOfPieces;
    private selectedPiece;
    //actions like select a piece, dropa piece
}

class Piece{
    private pieceID
    private ArrayOfPieceStates
    //handles the initial creation of pieceStates and returns the current state
}

class PieceState{
    private stateDimensions
    // the particular rotation of a piece, aware of it's dimensions.
}

可能这个结构应该作为一个整体进行重新设计,但我们假设它刚才可以。

问题:还有一个JPanel负责处理图形,它需要知道当前拼图的PieceState来绘制它。然后,面板的绘制方法获得具有以下请求的尺寸:

PuzzleController.getPiece().getState().getDimensions() 

这似乎是不好的做法,因为它完全破坏了封装,就像我现在所学到的那样。当我希望重新设计拼图结构时,这些吸气剂链将会破裂;

然后我想我可能会遵循“告诉不要问”原则来绘图:

PieceController.drawPiece(drawingInfo) // called by the graphics Panel
Piece.drawPiece(drawingInfo) // called by PieceController
PieceState.drawState(drawingInfo) // called by Piece, now here we are aware of piece dimensions so drawing can take place.

(不是实际代码中的drawingInfo是绘图方法所需的一行参数。)

在某种程度上,我已经实现了封装,因为第一个drawPiece方法是所有图形面板需求,并且它不需要担心这些部分是如何进一步构造的。但现在感觉我只是扭转了信息依赖,并没有取得多大进展。

首先是:绘图方法需要绘制当前puzzlePiece状态的维度信息。 现在它变成了:puzzlePiece的状态需要有关图形环境的信息来执行绘图操作(例如在屏幕上绘制这个部分)。

现在,当PieceState的绘图方法需要额外的不同输入并且此方法的声明发生更改时(例如,可能需要更多信息),对绘图方法的调用必须一直“改变”。

结论和实际问题 所以基本上问题是:旧情况违反封装,新情况可能不会,但似乎也不是封装原则的可靠实现。所以我的问题是:你有什么想改进这个设计?你将如何实现拼图,它们的状态和绘图操作呢?

2 个答案:

答案 0 :(得分:3)

构建一个知道如何绘制PieceDrawer的{​​{1}}。我强烈建议以下分离:

  • 模型类:保留并允许访问和修改内部应用程序状态,但不知道它们将如何被操纵或表示。你的Piece / PieceContoller / PuzzleController课程应该落在这里。据我所知,PieceState应该合并为Piece(因为它将不再包含那么多数据)。你的PuzzleController现在只知道如何修改模型类状态,但不知道用户输入。
  • View + Controller类:严格用于UI。通过模型的高级方法访问模型,但尽可能将实际游戏委托给模型。您的PieceDrawer和GamePanel(JPanel)类将属于此类别。 GamePanel将负责收集用户输入并在PuzzleController中执行移动,然后使用PieceDrawer绘制每个部分。

这个设置唯一的丑陋点是PieceDrawer和Pieces之间的耦合。另一方面,你将所有这些耦合放在一个地方,并且所有作品的片断绘画可能都相似。通过替换GamePanel和PieceDrawer,您可以将整个应用程序转换为基于文本的,而无需触及任何模型类。或者为用户提供片段表示选择(使PieceDrawer成为一个接口,有几个类实现它们)......

答案 1 :(得分:1)

PieceState应该是Piece的内部类。然后,DrawPiece可以使用PieceState来确定自己绘制的对象。