【问题标题】:What is the best design approach for attributes that are not directly related to an entity? [closed]与实体不直接相关的属性的最佳设计方法是什么? [关闭]
【发布时间】:2018-08-08 07:03:52
【问题描述】:

我想用 Java 创建一个模拟库的迷你应用程序。我创建了一个名为Book 的类,它具有以下属性:

public class Book {
    private final String ISBN;
    private String title;
    private String author;
    private String domain;
    private int numberOfPages;
}

我想再添加两个属性:stock 和 price。但这些属性与真正的书没有直接关系(如 ISBN 或 title),所以我不知道在哪里添加它们:在 Book 或其他上课...

一个想法是创建一个名为 BookView 的新类(不确定它是否是最佳名称)并添加如下属性:

public class BookView {
    private Book book;
    private short stock;
    private float price;
}

另一个想法是扩展 Book 并创建一个 BookWithDetails 子类来添加股票和价格,但我不确定继承是否适合这种情况:

public BookWithDetails extends Book {
    private short stock;
    private float price;
}

对于此类情况,最好的方法是什么?

【问题讨论】:

  • “存货”是指有多少本书?
  • 库存将表示存储库中有多少此类书籍。 示例:10 本书 Thinking in Java,第 4 版
  • 所以管理类只针对某种类型的书,对吧?所有书的标题都一样吗?
  • 是的,你没看错。股票和价格描述了一本特定的书。例如,10 个 Thinking in Java,每个 50 美元。
  • 您的 BookView,也许更好地命名为 BookStock,是要走的路。

标签: java oop architecture composition


【解决方案1】:

附加属性不属于Book 有两个原因:

  • 他们描述了其他东西 - 他们描述了很多以特定价格出售的书籍,而不是描述这本书,并且
  • 一本书可能有多个此类属性 - 理论上,您可能有五本书每本 10 美元,三本每本 8 美元。

因此,您的 BookView 类是代表一本书的好选择,除非我将其重命名:

public class BookLot {
    private Book book;
    private short stock;
    private float price;
}

还可以考虑将price 更改为int,并理解它代表美分或所需货币的任何值。这是因为float 和double 不太擅长表示小数,而BigDecimal 可能对于表示微小的十进制数来说太浪费了。

【讨论】:

  • 从这个答案中剔除。如果您需要准确的价格,请查看 Java 的 Currency Object
  • 为什么BigDecimal 会“太浪费”?使用int 听起来像是一种微优化。 BigDecimal 可以很容易地坚持可读的美元/美分金额,同时让计算始终返回正确的结果。
  • @MickMnemonic 好吧,OP 似乎非常注意他的对象的大小 - 他使用 short 和 float 代替 int 和 double,所以我认为他不是会非常喜欢BigDecimal。这只是一个建议,实际上,实际答案几乎在顶部的两个要点之后结束。
【解决方案2】:

在您的场景中,创建一个类似于BookView 的类(如您的帖子中所示)似乎是最佳选择:

public class BookManager {
    private short stock;
    private float price;
    private Book book;
}

这样,经理类将有关图书价格和数量的额外信息与实际图书本身分开。

因为字段被声明为private,您应该添加setter 和getter 方法来检索字段的值。作为一些 getter 方法的示例:

public short getStock() {
    return stock;
}

public float getPrice() {
    return price;
}

public Book getBook() {
    return book;
}

【讨论】:

    【解决方案3】:

    基本上,答案就在您的问题中:与实体不直接相关的属性的最佳设计方法是什么?

    如果您需要扩展一个具有与该对象无关的特征的对象,请考虑组合。如果扩展对象是前一个,考虑继承。

    没错,名字不是最好的,可以说是BookProduct 或BookCommodity(不太喜欢这个……)

    public class BookProduct {
        private Book book;
        private short stock;
        private float price;
    }
    

    【讨论】:

      【解决方案4】:

      只是在这里与其他人有一个不同的看法:我认为您应该在Book 类中同时拥有stock 和price。让我详细说明:

      什么是真实的?你如何定义“真实”?

      有时人们会说,在 OO 中,我们模拟了“现实世界”。这并不完全正确。我们为业务建模,我们称业务领域中存在的一切“真实”。并非所有这些东西都是在传统意义上实际上是真实的,并且大多数专业(即“企业”)都有特殊的术语,这些术语可能会为单词分配不同的语义,而不是它们的“传统”日常含义.

      什么是“书”?

      我的母语不是英语,但我相信“书”这个词有多种含义。 “书”这个词可能指的是一组物理对象,或者是指一个单一的、具体的物理对象。

      例如:作者 X 有一本新书。或者:我可以借那本书吗?

      图书馆

      事情变得更加复杂,因为您的域是一个“库”。只需与图书管理员(即您所在域中的“业务”人员)交谈即可。

      图书管理员会说:“我目前的 BookView 库存是……”吗?她可能不会这么说,她会说:“我目前的 Book X 库存是……”。或者类似的东西。

      另外,她将如何称呼您可以检查的单个物理对象?她很可能会说:“这是您的副本第 X 本书。”或类似的东西。

      建模

      现在,我们知道域中存在哪些“事物”,让我们看看我们如何对其建模。在 OO 中,我们不太关心数据,因此这些数据所在的位置实际上并不那么重要。

      重要的部分是行为,这些“东西”可以为我们提供什么。我的第一次尝试是这样的:

      public interface Book {
          Copy checkout();
      }
      
      public interface Copy {
          void return(); // I know, keyword
      }
      

      可能我需要Book 中的stock 和price 来促进checkout(),但根据我分配给Book 的行为,这是次要的。没有行为,数据就无关紧要了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        相关资源
        最近更新 更多