【发布时间】:2010-05-10 11:45:46
【问题描述】:
这个问题在我脑海中出现了好几次。
让我通过一个例子来解释我的问题。
假设我有两个课程: 1-网格。 2- 单元格。
现在单元格的位置“应该”存储在网格类中,而不是单元格类本身中。假设单元格想通过网格中的方法获取其位置。
它怎么能做到这一点?请记住,单元格是由 Grid 类创建/初始化的。
有什么好的OO方法来解决这个问题?
谢谢
【问题讨论】:
这个问题在我脑海中出现了好几次。
让我通过一个例子来解释我的问题。
假设我有两个课程: 1-网格。 2- 单元格。
现在单元格的位置“应该”存储在网格类中,而不是单元格类本身中。假设单元格想通过网格中的方法获取其位置。
它怎么能做到这一点?请记住,单元格是由 Grid 类创建/初始化的。
有什么好的OO方法来解决这个问题?
谢谢
【问题讨论】:
我认为这不是一个好的设计。如果单元格需要知道它的位置,它应该自己持有它并为网格提供访问它的方法。
【讨论】:
我会这样看:
这样,您可以将“单元格”视为网格内的坐标。
【讨论】:
为什么单元格需要知道它在网格中的位置?似乎细胞应该不知道它的位置。 如果您仍然需要这个 - 单元格可以保存指向其封闭网格的指针,并且可以向其询问位置(像这样,在单元格类中:getGrid().getLocation(this))
【讨论】:
最好的方法是向网格询问特定单元格的位置。
另一种解决方案是在单元格的构造函数中为单元格提供一个指向网格的指针。当单元格被请求其位置时,它可以从网格函数返回位置。
【讨论】:
如果您想让单元格知道它的位置,那么只需将其放在单元格内即可。将其排除在课堂之外是没有意义的,并不是说单个单元格可以在不同的网格中使用(因为您已经想要获取它的位置并且设置了这样的限制)。
或者,如果需要知道位置的单元格方法是从网格调用的,那么我只需将位置作为参数传递给该方法。
在一些非常特殊的情况下,您可能会将对网格的引用存储在单元格中,或者将其作为参数传递给它的方法,但感觉不对,因为引入了太多的耦合。
【讨论】:
这很简单,只要让Cell的构造函数取它的位置,假设这是构造函数:
public:
Cell(/*assume this is a generic type*/T value, int i, int j)
{
}
你为什么要这样做?首先是因为在您创建了一个单元格之后,它的位置几乎是固定的,除非您将执行诸如“插入”之类的专门操作。我不建议在 Grid 上调用方法,或者在本地保留 Grid 实例。
【讨论】:
对我来说,单元格似乎没有必要知道它在网格中的位置。重要的是,不是单元格从网格中获取其位置,而是网格在需要时将位置提供给单元格!所以 Grid 调用了 Cell 的一个方法,来做这件事。反之亦然。
最合乎逻辑的是 Grid 包含许多单元格,因此它“拥有”它们(例如,创建单元格、移动它们或其他任何方式)。因此,Cell 不应该对 Grid 有任何了解。
单元格本身包含一些信息。根据网格中的位置,可能需要刷新此信息或进行其他操作。然后你可以在 Cell 中有一个方法,由 Grid 调用来执行此操作。如果需要,该方法可能会接受位置参数,但单元格本身并不将它们作为成员。
【讨论】:
正如 Neil 所建议的,如果单元需要知道它的位置,它应该存储它。
话虽如此,我认为细胞不需要知道它的位置。网格负责管理单元格,包括它们的位置、告诉它们在哪里绘制自己等。单元格应该负责单元格包含的内容——例如,数据、格式信息等。
所以单元格永远不需要知道它在网格中的位置。它可能需要做一些事情,比如自己绘制,但这应该根据网格传入的屏幕坐标来完成。网格应控制绘制哪些单元格以及在何处绘制。细胞应该只做他们被告知和在哪里做的事情。
【讨论】:
网格可以使用某些函数搜索自身的单元格,该函数可以通过缓存或单元格到整数的 n 元组的字典/映射来优化。
【讨论】:
我会考虑将位置存储在每个单元格对象中,并且网格对象应该包含一组单元格,即创建的数量。这样我就可以解决我将面临的一些问题。
【讨论】:
如果这是grid 的责任,那么您必须让cell 知道它属于什么grid。将此添加到单元格的构造函数中。
这里你要考虑的唯一问题是知道位置到底是谁的责任。
【讨论】:
我猜你说的是网格中单元格的位置不是其“Cell-ness”所固有的,可以这么说,你希望拥有独立于 @ 的 Cell 的概念987654324@,因此单元格对象不应包含任何特定于网格的信息。
我不确定这种区别有多大价值,但如果你想要,有几个选择:
Cell 设为基类,并从中派生GridCell。正如其他答案所暗示的那样,GridCell 包含指向包含 Grid 对象或其位置的反向指针。Decorator pattern 之类的东西将特定于网格的信息和接口添加到Cell 对象。再一次,闻起来好像我们让这件事变得比现在更难了——我不确定拥有一个不属于 Grid 的 Cell 是否有意义,而且我没有看到让Cell 对象保持其在网格中的位置是有害的。事实上,让Grid 对象维护一个简单的Cell 对象集合更简单,每个对象负责知道它们在Grid 中的位置。
【讨论】:
工厂方法设计模式
定义一个用于创建对象的接口,但让您的子类决定要实例化哪个类。工厂方法定义了一个用于创建对象的接口,但让子类决定要实例化哪些类。
【讨论】: