哪个班级设计更好?

时间:2008-09-02 04:34:21

标签: oop class-design

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

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;
}

OR

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;
}

11 个答案:

答案 0 :(得分:54)

通过认识到继承模拟“IS-A”关系,而成员模型为“HAS-A”关系,可以简单回答这个问题。

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

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

答案 1 :(得分:18)

我不喜欢任何一个。当某人既是会员又是员工时会发生什么?

答案 2 :(得分:15)

问自己以下几点:

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

总的来说,在代码复杂性和所需效率的限制下,努力模拟程序模拟的现实。

答案 3 :(得分:12)

我认为组合总是比继承更好(通常)。如果员工和会员真的是用户,并且他们互相排斥,那么第一个设计就更好了。考虑您需要访问Employee的UserName的场景。使用第二种设计:

myEmployee.UserInfo.UserName

这很糟糕(Demeter法则),所以你要重构:

myEmployee.UserName

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

答案 4 :(得分:12)

不错的问题,虽然为了避免分散正确错误,我会考虑询问每种方法的优缺点 - 我认为这就是你的意思是好还是坏,为什么。无论如何......

第一种方法又称继承

优点:

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

缺点:

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

第二种方法又名作文

优点:

  • 很好地映射到关系表,结构化编程等非oop场景
  • 直接(如果不一定方便)增量扩展关系和行为。

缺点:

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

这些列表+提到的问题Jon Limjap将帮助您做出决定并开始使用 - 然后您就可以找到正确的答案应该是什么; - )

答案 5 :(得分:7)

您还可以将员工视为用户(人员)的角色。用户的角色可以及时更改(用户可能失业)或用户可以同时拥有多个角色。

真实时,继承会更好。""关系,例如Apple - Fruit。但要非常小心:圆圈 - 椭圆不是真的"是一个"关系,因为cirlce的自由度较低"比椭圆(圆是椭圆的状态) - 参见:Circle Ellipse problem

答案 6 :(得分:5)

真正的问题是:

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

这些实体可以是三个完全不相关的实体,这将决定您的第一个或第二个设计是否有效,或者是否有其他完全不同的设计。

答案 7 :(得分:4)

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

那就是说,第二个更好,因为它有利于构成而不是继承。

答案 8 :(得分:3)

陈述您的要求/规格可能有助于达到“最佳设计” 你的问题目前也是“主题 - 读者解释”。

答案 9 :(得分:2)

这是你应该考虑的一个场景:

如果同一用户既可以是员工又可以是会员,则最好使用组合(第2个示例)。为什么?因为对于表示同一用户的两个实例(Employee和Member),如果用户数据发生更改,则不必在两个位置更新它。只有User实例包含所有用户信息,并且只有它必须更新。由于Employee和Member类都包含相同的User实例,因此它们将自动包含更新的信息。

答案 10 :(得分:0)

还有三个选项:

  1. User类包含员工和成员的补充信息,未使用的字段为空(特定ID的{​​{1}}表示用户是否为员工,成员,两者或其他)。

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

  3. 如上所述,但User类包含某种User的集合。该方法具有便于向用户运行属性的运行时间的优点(例如,因为雇用了ISupplementalInfo)。使用前面的方法时,必须为不同的属性组合定义不同的类;将“会员”变成“会员+客户”需要不同的代码才能将“员工”变成“员工+客户”。后一种方法的缺点是它会使得更难以防止冗余或不一致的属性(使用类似Member的东西来保存补充信息可能有效,但看起来有点“笨重”)。

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