将域对象用作键是一种好习惯吗?

wax*_*ing 17 java oop domain-driven-design

将域对象用作映射(或"获取"方法)的键是一种好习惯,还是仅使用域对象的id更好?

用一个例子解释起来比较简单.假设我有Person类,Club类和Membership类(连接其他两个).也就是说,

public class Person {
    private int id; // primary key
    private String name;
}

public class Club {
    private String name; // primary key
}

public class Membership {
    private Person person;
    private Club club;
    private Date expires;
}
Run Code Online (Sandbox Code Playgroud)

或类似的东西.现在,我想getMembership向Club 添加一个方法.问题是,如果此方法采用Person对象:

public Membership getMembership(Person person);
Run Code Online (Sandbox Code Playgroud)

或者,一个人的身份:

public Membership getMembership(int personId);
Run Code Online (Sandbox Code Playgroud)

哪个是最惯用的,哪个最方便,哪个最合适?

编辑:很多非常好的答案.我没有暴露id,因为"人"(你可能已经意识到,我的真实域名与人和俱乐部没有任何关系......)实例很容易获得,但现在它在内部存储一个HashMap在id上进行了哈希 - 但至少我在接口中正确地公开了它.

dsm*_*ith 5

不要使用id的男人,这只是提到的所有原因的一个坏主意.你会锁定自己的设计.让我举个例子.

现在,您将会员资格定义为俱乐部与人员之间的映射.理所当然,您的会员资格应该是俱乐部对"会员"的地图,但您假设所有会员都是人,而且由于所有人的身份都是独一无二的,您认为您可以使用该身份证.

但是,如果将来您希望将您的会员资格概念扩展为"家庭成员资格",您可以为此创建一个Family表和Family类.以良好的OO方式,您可以提取名为Member的Family和Person的界面.只要两个类都正确地实现了equals和hashCode方法,就不必触及其他代码.就个人而言,我会事先定义成员界面.

public interface Member {
}

public class Person implements Member {
    private int id; // primary key
    private String name;
}

public class Family implements Member {
   private int id;
   private String name;
}

public class Club {
    private String name; // primary key
}

public class Membership {
   private Member member;
   private Club club;
   private Date expires;
}
Run Code Online (Sandbox Code Playgroud)

如果您在界面中使用了ID,则需要强制执行键值的跨表唯一性,或者维护两个单独的映射并放弃优秀的多态接口.

相信我,除非您正在编写一次性的一次性应用程序,否则您希望避免在界面中使用ID.