1

我正在建模一个类图,我完全被这个问题所困扰:

我的新 Web 应用程序有“卡片”(关于主题的条目),用户可以修改,à là wiki。但与 wiki 不同的是,不同的卡片拥有不同的数据。与 wiki 不同的是,卡片与数据库中的其他卡片明确相关。让我向您展示我最初是如何使用一个虚拟示例设计它的:

/** Similar to strategy/bridge pattern */
class Card<T extends CardInfoVersion> is composed of T // container of versions
class CardInfoVersion // one version
class Painting extends CardInfoVersion 
class Museum extends CardInfoVersion is composed of Paintings

优雅,干净,但错误。使用这种方法,博物馆与绘画版本相关联,而不是与绘画本身相关联。我想到的第一个解决方案是这个:

class Card<T extends CardInfoVersion> is composed of T
class CardInfoVersion
class Painting extends CardInfoVersion
class Museum extends CardInfoVersion is composed of Card<Painting>

这种方法闻起来很臭。CardInfoVersion 下的类层次结构很大,因此 UML 模型将不可读,并且 Card 类将充满对 CardInfoVersion 子类的 ORM 引用。然后我想出了这个:

class Card is composed of proposedModifications: Set<Card>
class Painting extends Card
class Museum extends Card is composed of Paintings

这也有气味。实际上,自从版本消失以来,这一切都搞砸了。它还要求管理员验证对卡片的提议修改。

我真的不知道如何解决这个问题。请记住:如果 CardInfoVersion 子类不相互关联,原始设计就可以了。

请帮忙!

4

2 回答 2

0

@Michael 有一个很好的观点。 博物馆是一个领域对象,绘画也是。听起来您正在使用“卡片”来收集各种人对绘画的评论。这表明CardFile是您要建模的内容。CardFile将是Cards的集合。卡片具有对相关博物馆或绘画的引用。

这里有一些提示:

  • 写出一些用户故事或用例。你过早陷入程序员思维;先想想你想做什么。如果你没有最喜欢的方式,那么使用这个模型:“某人”“做某事”“得到一些结果”。因此,例如,“我得到所有关于 Magritte 'Ceçin'es pas une pipe' 的卡片,以便找出哪个博物馆拥有它。”

  • 为这些类编写一些“用户代码”。伪代码很好,但它确实有助于提出界面。

所以你可能会写:

cards := cardfile.getAllCards(ceciNesPas)
for each card in cards
do
    print card.getPainting().getMuseum()
od

我根本不是发誓这是最好的方法,而是一个插图。

  • 如果这里的“版本控制”是有许多卡片与同一张画相关联,那么现在你已经设置好了。如果卡片上的格式、方法、数据项随着时间而变化,那么您需要确定卡片的具体内容,并将其设为超类。然后,您可以使更高版本的 Cards 成为 Card 的新子类:保持不变的东西在超类中,不同的部分是子类的业务。
于 2009-04-11T19:36:17.753 回答
0

我会采取领域驱动的方法。您的用户会称它们为“卡片”吗?这似乎是一个技术问题,但您将技术问题(卡片)与领域问题(博物馆、绘画)混为一谈。

在不了解您的域和用户的情况下,很难猜测您的最终解决方案是什么。

也许是这样:

class Museum extends Content is composed of Paintings
class Painting extends Content

class Card is composed of Set<Content>

这样,您就可以将域模型(博物馆、绘画)与视图模型(卡片)分开。我什至会更进一步,不使用继承(使用plain-old-java-object)路由,但我不知道你的确切实现。

如果您想了解有关这种设计风格的更多信息,这个播客很有帮助。

于 2009-04-11T17:09:09.620 回答