【问题标题】:Advise requested regarding proper use of encapsulation in Java就在 Java 中正确使用封装提出建议
【发布时间】:2010-08-13 08:43:05
【问题描述】:

我正在创建一个小益智游戏,只是作为一个爱好项目,但该项目现在已经达到了一个有相当多代码(大约 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 的绘图方法需要额外的不同输入并且此方法的声明发生更改(例如,它可能需要更多信息)时,对绘图方法的调用必须一直“向上”更改。

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

【问题讨论】:

    标签: java oop encapsulation


    【解决方案1】:

    构建一个知道如何绘制PiecePieceDrawer。我强烈建议以下分离:

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

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

    【讨论】:

    • 有点晚了,但非常感谢这个精心制定的答案!我已经做了这样的事情,现在模型的逻辑和绘图更好地分开了。然而,我现在所拥有的可能仍然不是 MVC 框架的干净实现。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多