【问题标题】:Designing a food ingredient class in OOP在 OOP 中设计食品配料类
【发布时间】:2016-03-10 17:25:22
【问题描述】:

我想向我的用户推荐食谱,所以我从 JSON 来源获取食谱(包括他们的成分)。

目前,可以通过三种方式获取成分:

  1. 3 tomatoes(无特定单位)
  2. 125ml of milk(体积单位,公制或英制)
  3. 500g of pasta(质量单位,公制或英制)

要求

我想使用 DDD 方法,即分层架构。

我需要能够按原样显示成分,就像我在上面的项目符号列表中建议的那样。用户可以在公制或英制视图之间进行选择。

  1. 3 tomatoes
  2. 125ml of milk 或 1/2 cup of milk
  3. 55g of pasta 或 2 ounces of pasta

我的挑战

我不确定如何设计类以尊重封装并确保易于维护设计。

我的第一个想法是用Unit 类表示单位,所以我的Ingredient 类将包含一个数量和一个单位。但在某些情况下,成分是无单位的。考虑到这个想法,我的IngredientPresenter 将如下所示:

public String present(Ingredient ingredient) {
    if ( ingredient.isUnitless() ) 
        return ingredient.getQuantity() + " " + ingredient.getName();
    else
        return ingredient.getUnit() + " " + ingredient.getName();
}

我不相信这种方法,因为我可以有许多不同类型的units,因此我的IngredientPresenter 会迅速增长(并违反OCP)。

然后,我想我可以使用 多态性。虽然这似乎是一个好方法,但我不知道在我的界面中公开什么,因为我的实现会完全不同。我需要在实现中公开我的方法,因此失去了多态性的所有好处。我的IngredientPresenter 如下所示:

public String present(Ingredient ingredient) {
    if ( ingredient instanceof UnitlessIngredient ) {
        UnitlessIngredient actualIngredient = (UnitlessIngredient) ingredient;
        return actualIngredient.getQuantity() + " " + actualIngredient.getName();
    } else {
        WithUnitIngredient actualIngredient = (WithUnitIngredient) ingredient;
        return actualIngredient.getUnit() + " " + actualIngredient.getName();
    }
}

实际上,我认为我的问题是我不知道如何正确表示单位,所以我正在寻求您的帮助。

感谢您的宝贵时间!

编辑

我不会只展示我的成分。在我的领域层中,我需要计算成分的营养成分。因此,根据其数量(或体积或质量),计算方式不同。一个简单地将营养成分乘以数量,而另一个必须执行 pro-rata。这是多态性的完美案例。

【问题讨论】:

  • DDD 架构不存在。看来您正试图过度设计解决方案。保持简单
  • 查看quantity 模式。对于您的无单位成分,只需使用“一块”单位。

标签: oop design-patterns architecture domain-driven-design


【解决方案1】:

肯定会使用多态性。

通常这样做的方式是 present() 在真空中不再是一个独立的函数,而是成为 Ingredient 的一个方法。

因此,您实质上调用Ingredient 将其自身呈现为字符串。可能有一些参数指示公制与英制,成分可能有一些用途,或者如果没有单位,它可能会忽略。简单、优雅、尝试过,效果很好。

【讨论】:

  • 那是个好主意,但它不允许我以不同的方式展示我的成分。假设我有一个 abbreviated 演示文稿和一个 full-text 演示文稿。此外,我的Ingredient 类(在域层中)知道它的表示(在更高级别)。
  • 第一部分:完全没有问题:在present() 中添加一个“缩写”标志,或者将其拆分为两种方法:presentAbbreviated() 和presentFullText()。第二部分:(“此外,......”)我不明白。
  • 这样下去,我们违反了Open/Closed principle,或者换句话说,我们需要添加方法来添加功能。我还有一个问题,我需要persist 我的成分,所以我将有一个方法将我的类转换为持久性的DTO。同样,我想改变我的坚持,这意味着我需要添加一个新方法:)。在 DDD 方法中,您的域层不应该知道(或知道)其他层。
  • 哦,我明白你的意思了。好吧,如果你真的想对设计原则如此挑剔,那么是的,这个答案并不适合。另一方面,您可以选择放宽设计纯度以提高生产力,换句话说,将这种方法视为一种务实的折衷方案。 (所以,拧开/关闭原则,多态表示完成任务。)
  • 在一个更复杂的项目中,在更接近设计核心的类中,我会争取纯度;但在您描述的情况下,这可能不值得。除非这是一项旨在找到如何以尽可能纯粹的方式完成工作的精确目标的练习;在这种情况下,我们希望会有更多的答案。
猜你喜欢
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
相关资源
最近更新 更多