2

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

在数据库中我认为问题解决了,每个类(Person、Client、Provider 和 Agent 表)一个表和一个从子类表的主键到超类表的主键的外键。(欢迎任何可能的改进:))

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

  • 一个名为 Person 的唯一类,其中包含子类中所有字段的联合。这将需要一个鉴别器字段才能知道 Person 的种类。问题是一个不是客户而是提供者的人,会将所有与客户相关的字段设置为空。

  • 一个名为 Person 的唯一类,具有子类的所有公共字段和三个“DTO-kind”属性,其中包含与每个子类相关的字段。这样我们只有一两个字段为空而不是几十个

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

这是一个网络应用程序。我在 UI 上使用 hibernate + spring 和 GWT

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

4

1 回答 1

11

IMO 继承不是最好的建模方法,我会尝试组合。

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

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

粗略的例子:

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 类与上面几乎相同,除了

  • 我使用 aEnumSet而不是 a List,因为这是专门为枚举量身定制的,
  • getRoleOfType()这里没有意义,所以我用hasRole().

    class Person {
      Set<Role> roles = new EnumSet<Role>();
      public void addRole(Role role) { ... }
      public void removeRole(Role role) { ... }
      public boolean hasRole(Role role) { ... }
    }
    
于 2010-09-27T15:45:25.490 回答