【问题标题】:Modeling Classes: hierarchy or attribute?建模类:层次结构还是属性?
【发布时间】:2018-10-17 08:20:18
【问题描述】:

我目前有这两个实体: 名义上的和熟悉的(家庭/亲属/亲戚)。

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

这 2 个类具有一个人的共同属性(名字、姓氏、出生日期......),它们是 2 种 Affiliate

我想将它们统一在一个超类中(泛化)Person,但我不知道我应该让 Titular 和 Familiar 扩展 Person 或添加 Person 作为它们的属性。 p>

Person 也必须单独存在(不能是抽象的),并且不是所有 Persons 都是 Affiliates 但!我还需要一种方法来建立/处理 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 {

【问题讨论】:

  • 如果对象代表人与人之间的联系,那么它们不应扩展 Person - 您的第二个解决方案看起来最好。
  • @OldCurmudgeon 如果您能花时间分享您对我的回答的看法,我会很好。

标签: java jpa hierarchy data-modeling


【解决方案1】:

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

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

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

  1. 可变或可选关系:例如,汽车的所有者可以更改,或者汽车可以没有所有者。猫不能停止成为动物而成为其他东西。
  2. 不同的公共 API:虽然工作量更大,但组合允许您手动转发要从内部指针公开的任何 API,从“父级”隐藏或更改内容。

一般来说,当 ClassA 是 ClassB 时,您会发现继承更有意义,因此您不会期望这会改变,也不会希望两个类都提供不同的 API。您会在任何地方看到此建议,它似乎非常适合您的示例。

【讨论】:

  • Composition 似乎是解决方案,除了名义/熟悉的人不能改变人。人 [1] ----- [0..*] 名义人 [1] ----- [0..*] 熟悉
  • 可能是这样。这完全取决于您的域。你会让人们脱离附属关系吗?名义上的人可以成为熟悉的人吗?反之亦然?如果是这样,则特定实例不遵循 IS-A 规则,而是具有临时关系。选择由您自己决定,因为问题的领域可以是任意复杂的。
【解决方案2】:

经过几次测试,我决定Composition而不是继承。 由于标签之一是“JPA”,因此必须映射/注释此解决方案

..所有可能的注释都不适合

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

如果 Titular 和 Familiar 从 Person 扩展而来,ORM 需要 Person 中的“DTYPE”列,这对我来说没用,因为无论一个人可以/将成为多少个 Titular 或 Familiar,它必须是一个人的登记册。

作为会员是一个“概念”或行为,我需要它来执行一些多态任务,它没有任何可持久的属性(现在!),我将为其创建一个接口。

@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..
}

【讨论】:

    【解决方案3】:

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

    Titular 是支持Affiliate 功能的Person

    Familiar 是一个Person,它支持Affiliate 的功能并与Titular 相关联。

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

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

    【讨论】:

      猜你喜欢
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多