OOP包含其他对象的对象的最佳实践

时间:2013-09-10 16:13:59

标签: java oop extends

我一直在努力实现这一目标的最佳方式。假设我有两个对象,一个是用户对象,另一个是注释对象。 Note对象将为患者保存注释,它将存储创建注释的人员以及上次更新的人员。什么是更好的选择:

选项A - 两个对象,一个只有Note特定信息,另一个是此对象的扩展名,其中包含患者/作者/更新程序的用户对象:

public class Note {
    private int noteId;
    private int patientId;
    private int authorId;
    private int updatedById;
    private String noteText;
    private Date noteDate;
}

public class NoteExt extends Note {
    private User patient;
    private User author;
    private User updater;
}

选项B - 一个Note对象,包含患者,作者,更新程序的用户类

public class Note {
    private int noteId;
    private User patient;
    private User author;
    private User updater;
    private String noteText;
    private Date noteDate;
}

选项A会使应用程序膨胀一大堆文件以进行其他对象/数据库调用,但在获取项目列表时会加快速度。 (在这种情况下使用extend也是正确的吗?)

选项B意味着不要担心在只有一个数据库功能的情况下记住要使用哪个对象,但是如果我获得用户创建的所有注释的列表,则会重复数据。

是否有选项C更好?

6 个答案:

答案 0 :(得分:2)

我不会直接将数据库建立在数据结构上。你如何用Java安排数据以及如何在数据库中安排数据不必相同,对一个人来说有意义的可能对另一个没有意义。

答案 1 :(得分:1)

根据您从数据库中检索的信息创建类似的关系,尤其是维护这种关系,并确保参照完整性,以便对一个项目的更改传播到其余项目(如果这是你想要的东西,否则你冒着重新创建同一记录的大量副本的风险,如果你不强制执行它可能会变得相当复杂。

这可能只是我,但是NoteExt类看起来像是在这里滥用继承。对我来说,第一堂课看起来非常精致和简单,我喜欢简单。您可能会有一些数据库上下文类,应用程序可以使用它来根据其ID(例如Database.userForId(int))查找用户或其他记录。对我而言,通过提供必需品来保持分离和简单是有意义的,但仍然提供了一种方法来轻松请求有关记录的更多信息。

正如其他人所提到的,有几种预先存在的替代方案(例如,Hibernate和JPA)可以为您映射数据库对象并创建您想要的那种关系。

为了回答下面的问题,我认为重要的是要注意我们创建的ORM不一定是我们为我们的观点提供的模型 - 不要误解我的意思,如果它是好的话总是那么容易,但正如你所说,有时他们需要更多的信息(甚至可能与数据库中的记录无关,而是与视图本身有关)。在C#的MVC框架中,我们面临着一个类似的问题,我们很多人通过专门为我们的视图创建单独的模型来克服这个问题,就像DefaultListModel维护一个数据向量在JList中显示一样(但是模型本身不会扩展Vector或任何其他集合。然后,您创建的新视图模型可以包含您希望在视图中显示的所有必要信息,还提供与其进行交互并对其进行修改的其他方法。

答案 2 :(得分:1)

计划C可能是这样的。使用一个复合创建所有对象作为单独的实体。使笔记更适用于其他应用程序。

public class Note {
    private int noteId;
    private String noteText;
    private Date noteDate;
}

public class PatientNote {
    private Note note;
    private User patient;
    private User author;
    private User updater;
}

答案 3 :(得分:1)

您似乎将对象设计与数据库设计混淆。这是可以理解的,因为您正在创建需要在数据库中表示的对象。但是,我发现在很多情况下,最容易“忘记”数据库并设计对象,然后使用模型映射器设计模式返回并为对象创建映射器,根据需要添加唯一ID。

所以你使用选项B,BUT来存储/加载数据库,你使用单独的映射器类:即UserMapper,NoteMapper等......然后秘密就是映射器使用了IdentityMap,所以当事情发生时如果通过ID加载,则使用对象的本地缓存副本,而不是一遍又一遍地访问数据库以获取userID的相同用户对象(例如)。

public class Note {
    private int noteId;
    private User patient;
    private User author;
    private User updater;
    private String noteText;
    private Date noteDate;
}

public class UserMapper {
    public User getUserById(int userId){
        User user = UserIdentityMap.getUser(userId);
        if(user == null) {
            user = fetchUserFromDb(userId);
            UserIdentifyMap.cache(userId, user);
        }
        return user;
    }
}

答案 4 :(得分:1)

选项B是正确的。您不应该考虑在对对象建模时如何保留数据。

答案 5 :(得分:0)

B是通常的做法,JPA预见到了这个问题:

  • EntityManager充当身份地图,并确保您一次没有多个对象副本,这样,如果您检索同一用户的备注列表,那么这些都将是引用相同的User对象。

  • 默认情况下,对其他对象的引用是惰性的,您只返回包含ID的代理,使开销等同于A.

相关问题