【问题标题】:Nested abstractions and Open-Closed Principle嵌套抽象和开闭原则
【发布时间】:2018-03-17 03:26:35
【问题描述】:

我即将实现一个文档生成器。我坚持遵循开闭原则,这给我带来了一些麻烦。要求如下:

  • 会有多种文件类型(即协议、授权书)
  • 会有多种文档格式(即 XML、JSON、HTML、PDF)
  • 每种文档类型都需要在文档中显示一组不同的数据(即客户详细信息、全能详细信息)

由于我选择遵循开闭原则,我强烈希望避免使用 switch 语句。这意味着我需要为特定类型的文档和格式类型引入一些抽象和实现。

是否需要提供 m x n 类实现,其中 m 是文档类型的数量,n 是文档格式的数量?我觉得这是错误的做法。能否请您给我一些提示如何正确设计这样的文档生成器?

【问题讨论】:

  • 我从来没有想过要始终尊重某个原则。您不应该如此专注于 O/C 或任何其他指南,您应该专注于理解领域并在此基础上进行设计。值对象和适当的聚合是这里的关键。
  • 你所说的“适当的聚合”是什么意思?请你举个例子好吗?
  • 正确的聚合意味着您需要正确识别域所见的每个文档模型。基本上,您需要了解每个文档的每个细节及其自身的约束和规则。它与代码、OOP、SOLID 等无关。您需要了解领域如何思考和处理事物,即您需要成为领域专家,至少在这个特定主题上。像领域一样思考,使用领域自己的语言。看不到类、函数等。
  • 你考虑过非循环访问者模式吗? stackoverflow.com/a/11437892/1168342
  • m x n 个模块来自 OCP。就像@MikeSW 所说,获得正确的域更好。我会让它正常工作,然后考虑在出现新格式或文档类型时重构为不那么脆弱的东西。

标签: oop design-patterns solid-principles open-closed-principle


【解决方案1】:

由于每种格式的行为完全不同,因此好的设计是通过实现一个通用接口(例如“IFormatter”)为每种格式创建不同的类。您可以将接口“IFormatter”注入需要调用文档格式化程序的客户端类。您可以通过不同的方式来完成对象创建的职责。一种是简单的工厂方法(我个人不是工厂方法的忠实粉丝)。另一种方式是责任链。您可以在找到匹配项时链接对象创建,它将创建相应的对象。

无论哪种方式,一旦您构建了客户端类,您就再也不需要修改它了。如果您想将文档格式化为另一种格式,那么只需通过实现“IFormatter”接口创建一个新类即可。

【讨论】:

    【解决方案2】:

    我会给你一些提示

    • 如果每种文档类型至少使用一个不同的概念并具有不同的业务约束,请为每种类型创建一个类。不要为干燥而出汗。唯一可重用的应该是用于封装文档每个细节的值对象。
    • Html、PDf 等是导入/导出格式。充其量是与实际文档相关联的元数据。如果它很重要,您可以拥有一个像 FormattedContent 这样的 Value 对象,它有 2 个属性:FormatContent

    关于switch.. 你有相当奇怪的约束。但是你可以用字典代替,没有开关!也许还有一个抽象工厂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 2012-09-02
      • 1970-01-01
      • 2017-12-01
      • 2017-06-19
      相关资源
      最近更新 更多