哪个类设计更好,为什么?

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”关系,就可以简单地回答这个问题。

  • 员工就是用户
  • 员工有用户信息

哪一个是正确的?这就是你的答案。

其他提示

两者我都不喜欢。当某人既是会员又是雇员时会发生什么?

问自己以下问题:

  • 你想为员工建模吗 用户?如果是这样,就选择继承。
  • 你想为员工建模吗 用户信息?如果是这样,请使用组合。
  • 用户(信息)和员工之间是否涉及虚拟功能?如果是这样,请使用继承。
  • 一个 Employee 可以有多个 User (info) 实例吗?如果是这样,请使用组合。
  • 将 Employee 对象分配给 User (info) 对象是否有意义?如果是这样,请使用继承。

一般来说,在代码复杂性和所需效率的约束下,努力对程序模拟的现实进行建模。

我不认为组合总是比继承更好(只是通常)。如果Employee和Member确实是Users,并且它们是互斥的,那么第一个设计会更好。考虑您需要访问员工的用户名的场景。使用第二种设计,您将拥有:

myEmployee.UserInfo.UserName

这是不好的(德墨忒耳定律),所以你可以重构为:

myEmployee.UserName

这需要 Employee 上的一个小方法来委托给 User 对象。所有这些都被第一个设计所避免。

好问题,虽然是为了避免分心 正确的错误的 我会考虑询问每种方法的优缺点——我认为这就是你所说的更好或更差的意思以及原因。反正 ....

第一种方法又称继承

优点:

  • 允许多态行为。
  • 最初 简便。

缺点:

  • 可能 随着时间的推移变得复杂或笨拙 如果 添加了更多的行为和关系。

第二种方法又名组合

优点:

  • 很好地映射到非 oop 场景,例如关系表、结构化编程等
  • 很简单(如果不一定方便) 逐渐地 扩展关系和行为。

缺点:

  • 没有多态性,因此使用相关信息和行为不太方便

像这样的列表+问题 乔恩·林贾普 提到的将帮助您做出决定并开始 - 然后您可以找到 正确的 答案应该是;-)

您也可以将 Employee 视为 角色 用户(人)的。用户的角色可以随时间改变(用户可能失业)或者用户可以同时拥有多个角色。

当存在时继承要好得多 真实的 “是”关系,例如苹果 - 水果。但要非常小心:圆 - 椭圆不是真正的“是”关系,因为圆比椭圆具有更少的“自由度”(圆是一个 状态 椭圆) - 参见: 圆椭圆问题.

真正的问题是:

  • 用户背后的业务规则和用户故事是什么?
  • 员工背后的业务规则和用户故事是什么?
  • 会员背后的业务规则和用户故事是什么?

它们可以是三个完全不相关的实体,也可以不是,这将决定您的第一个或第二个设计是否可行,或者是否需要另一个完全不同的设计。

两者都不好。太多的可变状态。您不应该能够构造处于无效或部分初始化状态的类的实例。

也就是说,第二个更好,因为它更倾向于组合而不是继承。

说明您的要求/规格可能有助于实现“最佳设计”。
目前你的问题太“取决于读者的解释”。

您应该考虑以下场景:

如果同一用户可以同时是员工和成员,则组合(第二个示例)是更好的选择。为什么?因为对于代表同一个 User 的两个实例(Employee 和 Member),如果 User 数据发生变化,您不必在两个地方更新它。只有 User 实例包含所有 User 信息,并且只有它需要更新。由于 Employee 和 Member 类都包含相同的 User 实例,因此它们将自动包含更新的信息。

另外三个选项:

  1. User 类包含员工和成员的补充信息,未使用的字段为空( ID 某个特定的 User 将指示用户是否是雇员、会员、两者或其他)。

  2. 有一个 User 包含对的引用的类 ISupplementalInfo, , 在哪里 ISupplementalInfo 继承于 ISupplementalEmployeeInfo, ISupplementalMemberInfo, , ETC。适用于所有用户的代码可以使用 User 类对象和具有 User 参考可以访问用户的补充信息,但这种方法可以避免更改 User 如果将来需要补充信息的不同组合。

  3. 如上所述,但有 User 类包含某种集合 ISupplementalInfo. 。这种方法的优点是便于在运行时向用户添加属性(例如因为一个 Member 被录用了)。当使用前一种方法时,必须为不同的属性组合定义不同的类;将“成员”转变为“成员+客户”与将“员工”转变为“员工+客户”需要不同的代码。后一种方法的缺点是,它会更难防范冗余或不一致的属性(使用类似 Dictionary<Type, ISupplementalInfo> 保存补充信息是可行的,但看起来有点“笨重”)。

我倾向于第二种方法,因为它比直接继承更好地允许未来扩展。使用对象集合而不是单个对象可能会有点麻烦,但该方法可能比其他方法更好地处理不断变化的需求。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top