OOP 组织问题的最佳解决方案

发布于 2024-12-22 12:31:10 字数 306 浏览 1 评论 0原文

我有一个关于特定 OOP 问题的组织的快速问题。

假设我有一个地形类,里面充满了瓷砖。 Tile 类有多个派生类,即 Door。 Door 类有一个名为 open() 的方法,用于打开门,还有一个称为 close() 的方法,用于关闭门。这是非常有意义的,直到这两种方法都需要在打开和/或关闭之前检查某些内容。如何在门不知道其父对象的情况下以某种方式检查对象?

一个简单的解决方案是在调用 open() 之前检查路上是否有东西,但如果需要检查不同形状的不同类型的门,则会在更高级别上造成混乱。

看起来这会有一个简单的答案,但我似乎也经常遇到这个问题。

I have a quick question about the organization of a particular OOP problem.

Say I have a Terrain class, full of Tiles. There are multiple derivatives of class Tile, namely Door. The Door class has a method called open() which opens the door, and close() which closes the door. This makes perfect sense until both of these methods need to check for something in the way before opening and/or closing. How do I make a Door check for an object in the way without it knowing about its parent?

A simple solution would be to check for something in the way before calling open(), but if there was a different kind of door that needed to be check in a different shape, it creates clutter on the higher level.

It seems like this would have a simple answer, but it also seems like I run into this problem more often than not.

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

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

发布评论

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

评论(1

安稳善良 2024-12-29 12:31:10

一个答案是,门应该知道如何自行打开和关闭,并知道它们是否被阻挡。如果 Door 是一个类,则状态(is_openis_blocked)和行为(open_the_doorclose_the_door ) 应该驻留在 Door 类中。封装是面向对象范式的基本原则。

但现实世界的答案通常更加微妙。您能否提供一些有关该应用程序的背景及其需要完成的任务?有一些干净、简单的解决方案非常适合玩具应用程序,但更大的应用程序将需要更复杂的东西。

如何处理门is_blocked会带来一些设计问题。没有一种正确的设计,但有好的设计和坏的设计。区分好想法和坏想法不仅仅取决于设计原则,还取决于问题的背景。

如果我必须猜测的话,我猜您的应用程序是一个游戏。也许图块代表游戏板或地图的区域。您已经发现许多不同的对象可能必须进行交互,如果它们都直接相互引用,那将会很混乱。

  • 游戏通常有一个称为“游戏”或“棋盘”或“地图”的主对象。让主对象保存 Tile 层次结构中的事物集合(瓷砖、门等)。

  • 让主对象还保存可以阻挡门或以其他方式与瓷砖和门交互的事物的集合。

  • 现在在 Tile 类上创建一个名为 update() 的方法,该方法接受一个对象作为参数。

  • 并为 Door 类创建一个名为“blocked”的布尔属性。
    Door 的更新方法可能会执行如下操作:

    Door::update(BlockingObject 对象) {
     if(object.location == this.location)
          被阻止=真 
     }

  • door 超类上的方法可能不执行任何操作。像这样:

    Tile::update(BlockingObject obj) {
         //图块不能被阻挡
    }

  • 现在,在游戏循环内,包括一个将所有门设置为 blocked = false 的步骤。

  • 创建一些循环会要求所有图块检查它们是否被阻止。它在伪代码中可能看起来像这样:

    对于每个图块 {
         对于每个阻塞对象{
              瓦片.更新(对象)
         }
    }

  • 这是一个朴素但直接的设计,符合 OO 范式。

  • 该设计为图块/门和物体提供了每回合交互一次的机会,而不强迫它们相互引用。

  • 该设计对于几百个图块和对象来说效果很好,但对于数千个图块来说它会变得非常慢。

这是一个好的设计吗?

答案取决于应用程序的需求。

One answer is that Doors should know how to open and close themselves and know if they are blocked. If Door is a class, then both the state (is_open, is_blocked) and the behavior (open_the_door, close_the_door) should reside in the Door class. Encapsulation is a fundamental principle of the object-oriented paradigm.

But the real-world answer is usually more subtle. Can you provide some background on the application and what it needs to accomplish? There are clean, simple solutions that will work well for toy applications, but bigger apps are going to need something more sophisticated.

How to handle door is_blocked presents some design issues. There is no one right design, but there are good design and bad designs. Separating the good ideas from the bad ideas depends on more than just design principles-- it depends on the context of the problem.

If I had to take a guess, I'd guess that your application is a game. Maybe the tiles represent the area of the game board or map. You have identified that many different objects might have to interact and that it would be mess if they all referenced each other directly.

  • Games often have a master object called "Game" or "Board" or "Map". Let the master object hold the collection of things in the Tile hierarchy (tiles, doors, etc).

  • Let the master object also hold the collection of things that can block doors or otherwise interact with tiles and doors.

  • Now create a method named update() on the Tile class that accepts an object as a parameter.

  • And create a boolean attribute for the Door class called "blocked".
    The update method for the Door might do something like this:

    Door::update(BlockingObject object) {
     if(object.location == this.location)
          blocked = true 
     }

  • The method on the superclass of door might do nothing. Like this:

    Tile::update(BlockingObject obj) {
         //tiles cannot be blocked
    }

  • Now, inside the game loop, include a step where all the doors are set to blocked = false.

  • The create some loops ask all of the tiles to check if they are blocked. It might look something like this in pseudo code:

    For each tile {
         For each blocking object {
              tile.update(object)
         }
    }

  • This is a naive, but straight forward design that holds true to the OO paradigm.

  • The design gives tiles/doors and objects a chance to interact once per turn, without forcing them to hold references to one another.

  • The design will work fine for a few hundred tiles and objects, but it would become very slow for thousands of tiles.

Is it a good design?

The answer depends on the needs of the application.

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