Java中的重叠继承

发布于 2024-09-24 19:04:20 字数 693 浏览 9 评论 0原文

我有一个重叠的继承层次结构。系统了解可以是客户、提供商和代理的人员。一个人必须属于这些类别之一,但可以属于两个或三个,即一个人可以同时是客户和提供者。

在数据库中,我认为问题已经解决,每个类一个表(人员、客户端、提供者和代理表)以及从子类表的主键到超类表的主键的外键。 (任何可能的改进都将受到欢迎:))

问题出现在 Java 世界中,我不知道将此数据库设计映射到我的 Java POJO 的最佳方法。我有三种可能的棘手解决方法:

  • 一个名为 Person 的独特类,它包含子类中所有字段的并集。这需要一个鉴别器字段才能知道人是哪一种。问题是,不是客户端而是提供者的 Person 将把所有与客户端相关的字段设置为 null。

  • 一个名为 Person 的独特类,具有子类的所有公共字段和三个“DTO 类型”属性,用于保存与每个子类相关的字段。这样,我们只有一两个字段为 null,而不是数十个。

  • Person 的一个抽象类和七个子类,三个子类(即 Client、Provider、Agent、ClientProvider、ClientAgent ... ClientProviderAgent)的每个可能组合都有一个。 :S(当然,每个人都有相应的接口)

它是一个webapp。我使用 hibernate + spring 和 GWT 作为 UI

问题是:解决这个问题的最佳方法是什么?

I have an inheritance hierarchy with overlap. The system knows about People that can be Clients, Providers and Agents. A person have to belong to one of these classes but can belong to two or three, i.e. one Person can be a Client and a Provider at the same time.

In the database I think that the problem is solved, one table per class (Person, Client, Provider and Agent table) and a Foreign Key from the Primary Key of the subclasses table to the Primary Key of the superclass table. (Any possible improvement will be welcome :) )

The problem comes in the Java world, I don't know the best way to map this database design to my Java POJOs. I have three possible grotty workarounds:

  • A unique class called Person, with the union of all the fields in the subclasses. This will need a discriminator field in order to know wich kind of Person is. The problem is that a Person that is not a Client but is a Provider, will have all the Client-related fields set to null.

  • A unique class called Person with all the common fields to the subclasses and three "DTO-kind" properties that holds the fields related to each subclass. This way we only have one or two fields to null instead of tens

  • One abstract class for Person and seven subclasses, one per possible combination of the three subclasses i.e. Client, Provider, Agent, ClientProvider, ClientAgent ... ClientProviderAgent. :S (of course, everyone with their corresponding interfaces)

It's a webapp. I use hibernate + spring and GWT for the UI

The question is: which is the best way to solve this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遇到 2024-10-01 19:04:20

IMO 继承并不是对此进行建模的最佳方法,我会尝试组合。

您可以有一个 Person 类和多个 Role 类(实现一个公共接口,或者成为 Role 枚举的成员,具体取决于上下文),每个人都附加一个或多个 Role。

通过这种方式,您可以轻松添加新的角色类型,并动态地将角色附加到人员或从人员分离角色。 (如果需要,您也可以让人员没有角色。)

粗略示例:

interface Role {
  ...
}

final class Client implements Role {
  ...
}

final class Provider implements Role {
  ...
}

final class Agent implements Role {
  ...
}

class Person {
  List<Role> roles;
  public void addRole(Role role) { ... }
  public void removeRole(Role role) { ... }
  public Role getRoleOfType(Class<? extends Role> roleType) { ... }
}

更新:基于枚举的示例

如果角色对象没有状态,则这适用,因此您将相同的角色实例附加到每个人。

enum Role {
  CLIENT,
  PROVIDER,
  AGENT;
  // possible members, constructor etc.
}

Person 类几乎与上面相同,只是

  • 我使用 EnumSet 而不是 List,因为这是专门为枚举定制的,
  • getRoleOfType() 没有任何意义在这里,所以我将其替换为 hasRole()

    类人{
      设置<角色>角色 = new EnumSet();
      公共无效addRole(角色角色){...}
      公共无效removeRole(角色角色){...}
      公共布尔 hasRole(角色角色) { ... }
    }
    

IMO inheritance is not the best way to model this, I would try composition instead.

You could have a Person class and several Role classes (implementing a common interface, or being members of a Role enum, depending on the context), with each person having one or more Roles attached.

This way you can add new role types easily, and dynamically attach/detach roles to/from a person. (You can also have persons without a role, should the need arise.)

Rough example:

interface Role {
  ...
}

final class Client implements Role {
  ...
}

final class Provider implements Role {
  ...
}

final class Agent implements Role {
  ...
}

class Person {
  List<Role> roles;
  public void addRole(Role role) { ... }
  public void removeRole(Role role) { ... }
  public Role getRoleOfType(Class<? extends Role> roleType) { ... }
}

Update: enum based example

This is applicable if the role objects have no state, thus you attach the same role instance(s) to every person.

enum Role {
  CLIENT,
  PROVIDER,
  AGENT;
  // possible members, constructor etc.
}

The Person class is almost the same as above, except that

  • I use an EnumSet instead of a List, since this is tailored specifically for enums,
  • getRoleOfType() makes no sense here, so I replaced it with hasRole().

    class Person {
      Set<Role> roles = new EnumSet<Role>();
      public void addRole(Role role) { ... }
      public void removeRole(Role role) { ... }
      public boolean hasRole(Role role) { ... }
    }
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文