关于正确使用 Java 封装的建议

发布于 2024-09-14 08:16:10 字数 1593 浏览 4 评论 0原文

我正在创建一个小益智游戏,只是作为一个业余爱好项目,但该项目现在已经达到了有相当多代码的地步(大约 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.

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

以某种方式,我已经实现了封装作为第一个drawPiece 方法是图形面板所需的全部内容,无需担心各个部分的进一步结构。但现在感觉我只是扭转了信息依赖,并没有取得太大进展。

首先是:Drawing方法需要当前puzzlePiece状态的尺寸信息来进行绘制。 现在它变成了: puzzlePiece 的状态需要有关图形环境的信息来执行绘图操作(例如在屏幕上的哪个位置绘制拼图)。

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

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

I'm creating a little puzzle game just as a hobby project but the project has now reached a point that there is quite a lot of code (about 1500 lines). Although I've tried to prevent it, the code has become messy. I definitely want to clean up the code and make it more maintainable and readable while I still can.

There are 3 classes handling actions regarding puzzle pieces in my game:

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

Propbably this structure should be redesigned as a whole but let's assume that it's ok for just now.

The problem: There also is a JPanel that takes care of the graphics and it needs to be aware of the PieceState of the current puzzle piece to draw it. the drawing method of the panel then gets the dimensions with a request like:

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

This seems like bad practice as it breaks encapsulation totally as I've learned now. When I would deside to redesign the puzzle piece structure these chains of getters will break;

Then I thought I might follow the "Tell don't ask" principle for the drawing:

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.

(not that drawingInfo in the acutal code is a line of arguments that the drawing methods require.)

In some way I've implemented encapsulation as the first drawPiece method is all the graphic panel needs and it doesn't need to worry about how the pieces are further structured. But now it feels like I've only reversed the information dependency and haven't made much progress.

first it was: Drawing method needs the dimension information of current puzzlePiece's state to draw.
now it has become: puzzlePiece's state needs information about the graphical environment to perform drawing operations (where on the screen to draw the piece for example).

now when the drawing method of PieceState requires additional of different input and the declaration of this method changes (it might require more information for example) the calls to the drawing methods have to change all the way 'up'.

Conclusion and actual question
So basically the problem is: old situation violated encapsulation, new situation might not but also doesn't seem like a solid implementation of the encapsulation principle. so my question is: what are your ideas to improve this design? How would you implement Puzzle pieces, their states and drawing operation on them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猛虎独行 2024-09-21 08:16:10

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

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

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

Build a PieceDrawer that knows how to draw a Piece. I strongly suggest the following separation:

  • Model classes: keep and allow access and modification of internal application state, but know nothing whatsoever of how they are going to be manipulated or represented. Your Piece / PieceContoller / PuzzleController classes should fall in here. As far as I can see, PieceState should be merged into Piece (as it will no longer contain that much data). Your PuzzleController will now only know how to modify model class state, but nothing about user input.
  • View+Controller classes: strictly for UI. Access the model through the model's high-level methods, but delegate as much as possible about the actual game to the model. Your PieceDrawer and GamePanel (a JPanel) classes would fall in this category. The GamePanel will be responsible for gathering user input and executing the moves in the PuzzleController, and then painting each piece with the PieceDrawer.

The only ugly point with this setup is the coupling between PieceDrawer and Pieces. On the other hand, you have all that coupling in a single place, and piece-painting is likely to be similar for all pieces. By replacing the GamePanel and the PieceDrawer, you could convert your whole application to text-based, without touching any model classes. Or offer users a choice of piece representations (make PieceDrawer an interface, have several classes implementing them)...

花间憩 2024-09-21 08:16:10

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

PieceState should probably be an inner class of Piece. DrawPiece can then use the PieceState to determine who to draw itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文