在Java中重叠继承

lui*_*obo 2 java inheritance multiple-inheritance overlap

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

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

问题来自Java世界,我不知道将这个数据库设计映射到我的Java POJO的最佳方法.我有三种可能的问题解决方法:

  • 一个名为Person的唯一类,具有子类中所有字段的并集.这将需要一个鉴别器字段,以便知道人类的类型.问题是,不是客户端但是提供者的Person将所有与客户端相关的字段设置为null.

  • 一个名为Person的唯一类,包含子类的所有公共字段和三个"DTO-kind"属性,用于保存与每个子类相关的字段.这样我们只有一个或两个字段为null而不是数十

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

这是一个webapp.我使用hibernate + spring和GWT作为UI

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

Pét*_*rök 11

IMO继承不是模拟这个的最佳方式,我会尝试使用组合.

您可以拥有一个Person类和几个Role类(实现一个公共接口,或者是一个Role enum的成员,具体取决于上下文),每个人都有一个或多个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) { ... }
}
Run Code Online (Sandbox Code Playgroud)

更新:基于枚举的示例

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

enum Role {
  CLIENT,
  PROVIDER,
  AGENT;
  // possible members, constructor etc.
}
Run Code Online (Sandbox Code Playgroud)

Person类几乎与上面相同,除了

  • 我使用的EnumSet是a而不是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) { ... }
    }
    
    Run Code Online (Sandbox Code Playgroud)