哪个班级的设计更好?
哪个班级的设计更好,为什么?
public class User { public String UserName; public String Password; public String FirstName; public String LastName; } public class Employee : User { public String EmployeeId; public String EmployeeCode; public String DepartmentId; } public class Member : User { public String MemberId; public String JoinDate; public String ExpiryDate; }
或者
public class User { public String UserId; public String UserName; public String Password; public String FirstName; public String LastName; } public class Employee { public User UserInfo; public String EmployeeId; public String EmployeeCode; public String DepartmentId; } public class Member { public User UserInfo; public String MemberId; public String JoinDate; public String ExpiryDate; }
解决方案
回答
我都不喜欢。当某人既是成员又是雇员时会发生什么?
回答
只需通过承认继承为" IS-A"关系建模,而成员身份为" HAS-A"关系建模,即可简单地回答该问题。
- 员工是用户
- 一名员工有一个userinfo
哪一个是正确的?这就是你的答案。
回答
谁都不是好人。太多易变的状态。我们应该不能构造处于无效或者部分初始化状态的类的实例。
就是说,第二个更好,因为它更倾向于使用组合而不是继承。
回答
问问自己以下几点:
- 我们要为"员工就是用户"建模吗?如果是这样,请选择继承。
- 我们要为员工拥有用户信息建模吗?如果是这样,请使用合成。
- 用户(信息)和员工之间是否涉及虚拟功能?如果是这样,请使用继承。
- 员工可以拥有多个用户(信息)实例吗?如果是这样,请使用合成。
- 将Employee对象分配给User(信息)对象是否有意义?如果是这样,请使用继承。
通常,在代码复杂度和所需效率的约束下,努力为程序模拟的现实建模。
回答
真正的问题是:
- 用户背后的业务规则和用户故事是什么?
- 员工背后的业务规则和用户故事是什么?
- 成员背后的业务规则和用户故事是什么?
这可以是三个完全不相关的实体,它们将确定第一个或者第二个设计是否有效,或者是否要使用另一个完全不同的设计。
回答
我不认为合成总是比继承更好(通常)。如果Employee和Member确实是Users,并且它们是互斥的,则第一个设计会更好。考虑需要访问员工用户名的情况。使用第二种设计,我们将拥有:
myEmployee.UserInfo.UserName
这很糟糕(Demeter定律),因此我们可以重构为:
myEmployee.UserName
这需要一个关于Employee的小方法来委托给User对象。所有这些都可以通过第一种设计避免。
回答
说明要求/规格可能有助于获得"最佳设计"。
问题目前也是"根据读者的理解"。
回答
我们应该考虑以下情形:
如果同一用户既可以是雇员又可以是成员,则最好使用组合(第二个示例)。为什么?因为对于代表同一用户的两个实例(员工和成员),如果用户数据发生更改,则不必在两个位置进行更新。只有User实例包含所有User信息,并且只需要更新它。由于Employee和Member类都包含相同的User实例,因此它们将自动都包含更新的信息。
回答
这是一个很好的问题,尽管为了避免干扰是非,我会考虑询问每种方法的利弊-我认为这是意思,是好是坏,以及原因。反正 ....
第一种方法又称为继承
优点:
- 允许多态行为。
- 最初是简单方便。
缺点:
- 如果添加更多的行为和关系,则可能随着时间的流逝变得复杂或者笨拙。
第二种方法又名合成
优点:
- 很好地映射到非循环场景,例如关系表,结构化程序等
- 直接(如果不一定方便)可以逐步扩展关系和行为。
缺点:
- 没有多态性,因此使用相关信息和行为不太方便
像这样的列表以及乔恩·林贾普(Jon Limjap)提到的问题将做出决定并开始使用-然后,我们可以找到正确的答案;-)