建模 类:层次结构还是属性?

Modeling Classes: hierarchy or attribute?

我目前有这两个实体: 名义上的和熟悉的(Family/kin/relative)。

熟悉 [0..*]<------>[1] 有名无实

这 2 classes 具有一个人的共同属性(firstName,lastName,birthDate ....),它们是 2 种 Affiliate

我想将它们统一在一个超级 class(概括)Person 但我想不通的是我应该使 Titular 和 Familiar 扩展 Person 或添加 Person 作为它们的属性。

Person 也必须独立存在(不能抽象)并且并非所有 Persons 都是 Affiliates 但!我还需要一种方法来 establish/handle Titular 和 Familiar 的共同行为。

人物 [1]<------>[0..*] 名义

人 [1]<------>[0..*] 熟悉

名义上的 [1]<------>[0..*] 熟悉的

所以疑点是:

public class Titular extend Person
public class Familiar extend Person {

public class Titular implement Affiliate {
    private Person person;

public class Familiar implement Affiliate {
    private Titular t;
    private Person person;

或(第三个想法)

public class Person {
public abstract class Affiliate {
    protected Person person;
public class Titular extends Affiliate {

详细说明,我们需要以下行为(如果我理解正确的话):

Titular 是支持 Affiliate.

功能的 Person

Familiar 是一个 Person,它支持 Affiliate 的功能并与 Titular.

相关联

在阅读这两行足够多的次数后,一种似乎合理的可能解决方案是:

public class Titular extends Person implements Affiliate {

public class Familiar extends Person implements Affiliate {
    private Titular t;

在我看来,所有附属机构也是人(或者您对此有例外?)!所以正确的层次结构是:

Person --- Affiliate --- Titular 
                      \- Familiar

现在,关于继承或拥有指针...这称为组合 v/s 继承,两者都有很好的论据。选择作文的主要原因是

  1. 可变或可选关系:比如说,车主可以改变,也可以没有车主。一只猫不能停止成为动物而成为其他东西。
  2. 不同 Public API:虽然需要更多工作,但组合允许您手动转发任何 API 您想要从内部指针公开的内容,隐藏或更改 "parent" 如你所愿。

一般来说,当 ClassA IS-A ClassB 时,您会发现继承更有意义,因此您不会期望这种情况发生变化,也不希望两者 类 呈现不同的 API .您会随处看到此建议,它似乎非常适合您的示例。

经过几次测试,我决定 Composition 而不是继承。 由于标签之一是 "JPA",此解决方案必须是 mapped/annotated

..和 none 可能的注释套装

@Inheritance(strategy = InheritanceType.JOINED/SINGLE_TABLE/TABLE_PER_CLASS)

如果 Titular 和 Familiar 从 Person 扩展而来,ORM 需要在 Person 中有一个 "DTYPE" 列,这对我来说没用,因为无论一个人 can/will 中有多少 Titular 或 Familiar生活,它必须是一个人的寄存器。

作为附属是一种 "concept" 或行为,我需要它来执行一些多态任务,它没有任何持久属性(暂时!),我将为其创建一个接口.

@Entity
public class Persona {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;


@Entity
public class Titular implements Afiliado {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;
   @JoinColumn(nullable = false)
   @ManyToOne(optional = false)
   private Persona persona;

@Entity
public class Familiar implements Afiliado {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;
   @JoinColumn(nullable = false)
   @ManyToOne(optional = false)
   private Persona persona;
   @ManyToOne
   private Titular titular;

public interface Afiliado {
   public String getNumero();
   //trick but necessary
   public Persona getPersona();

   //another default Java 8 implementations..
}