【问题标题】:Class design for domain object and container of these objects领域对象的类设计和这些对象的容器
【发布时间】:2014-11-26 20:02:56
【问题描述】:

我们今天在工作中讨论了我们代码库中反复出现的情况: 假设我们的软件中有一个特定的域对象(例如客户)。此外,我们的系统中有一组与特定用例相关的客户。我们有适用于特定客户的业务逻辑(例如 getRevenue())和适用于整个客户组的其他部分(例如 getAverageRevenue()、getNumberOfActiveCustomers()...)。 组功能还包括更改组中某些客户或搜索组中某些子组等的方法。(例如 getCustomersWithoutOrdersSince())。

遇到这种情况你会怎么做:

  1. 创建一个 Customer 类和一个 CustomerGroup 类:CustomerGroup 类在私有成员 std::vector 中(或在 Java 中的 List 中)有它的客户。组相关功能作为 CustomerGroup 的成员函数实现。
  2. 只创建一个客户类,将客户的 std::vector(或列表)留给调用者:在客户的成员函数中添加单个客户功能。 CustomerGroup 相关功能实现为 Customer 的静态方法(例如:static int getAverageRevenue(vector &custVector) 或 Java 中的 static int getAverageRevenue(List))
  3. 编号的变化。 2(仅限 C++):只创建一个 Customer 类,将客户向量留给调用者,将 CustomerGroup 功能作为命名空间 Customer 中的非成员函数实现
  4. ...

您将如何实现这样的场景,或者您认为有哪些优点/缺点。

在“Effective C++”的第 23 条(“Prefer non-member non-friend functions to members functions”)中,Scott Meyers 提倡将东西移出非成员函数的类。在我看来,这类似于设计号 3。然而,我发现这个建议很奇怪且违反直觉。 @jrahhali 评论说,这可能是为了遵守单一责任原则。欢迎提出任何想法/帖子/网址(不幸的是,我没有找到关于第 23 项的任何好的讨论)。

提前感谢您的意见。

【问题讨论】:

  • 5.使用std::accumulate 并停止将所有内容硬塞到类层次结构中。
  • @Kerrek SB:我的例子有点误导和做作。组功能不仅提供简单的累积方法(如 getAverageRevenue()),还提供以各种方式修改客户对象、搜索客户子组的功能......我将更新示例以反映这一点
  • 啊。在这种情况下,请考虑我的回答具有误导性和做作。

标签: java c++ oop design-patterns


【解决方案1】:
  1. 我最喜欢这个。在 Customer 类中具有作用于客户的方法是直观的,而在 CustomerGroup 类中具有作用于对客户的组的方法也很直观。您还拥有 CustomerGroup 封装其对一组客户的表示,它为所有未来与组相关的操作提供了一个很好的位置。它不是静态的,因此您可以选择线程安全,如果这很重要的话。 CustomerGroup 还提供了比向量或列表更多的含义。

  2. 这也不错。您仍然提供了一个对相关行为进行分组的地方,但这次是在 Customer 类的静态方法中。我个人认为静态方法比 OO 更像程序化方法,因此,仍然更喜欢#1。但是,归根结底,#1 和 #2 非常相似,因为它们都实现了 DRY 方法。

  3. 这比 #2 更加程序化,但仍能获得相同的结果。

我想答案取决于您要如何编写 OO 和/或程序。

【讨论】:

  • 好吧,你说这更多的是使用哪种风格的问题。在讨论替代方案时,我有一种直觉,我肯定会选择 1 而不是 2,但除了封装之外,我想不出 1 比 2 的任何“硬”优势。
  • 顺便说一句。我遇到了 Meyers "Effective C++" Item 23 "Prefer non-member non-friend functions to members functions"。这将(至少对于 C++)提倡 2 或 3 号。对此有任何想法。在 Meyers 书中,将编译单元解耦列为潜在优势。
  • 多么有趣的发现。在研究了 Item 23 之后,我不明白外部化成员函数如何增加封装的论点。这似乎倒退了。我读到的第 23 条的解释让我想起了单一职责原则。也许迈耶斯用另一个名字来解释 SRP,但并不知道? SRP 并没有说从对象中剥离所有成员函数,而只是说那些“有理由改变”的成员函数。
  • 我在阅读第 23 项时也有同样的印象。起初我认为这可能更像是 C++ 特定的东西(与 java 不同,您可以在类之外存在方法,最大限度地减少头文件依赖,...)但也许你是对的,它是某种重新制定的 SRP。如果您减少特定类提供的功能,则会减少更改的可能性。但是话又说回来,您仍然希望将数据和功能组合在一起......
猜你喜欢
  • 1970-01-01
  • 2011-05-26
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多