C#中的聚合与继承,或替代方案

时间:2010-08-25 08:54:14

标签: c# .net oop

假设我有以下两个类:

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}
public class Customer: Person
{
    public string CustomerNumber { get; set; }
    public string PaymentTerms { get; set; }
}

现在,如果我有一个我想成为客户的人,据我所知,我有三个选择,我希望得到关于哪个是最好的以及任何其他选择的建议,也许使用C#4中的新动力学东西。

我可以向Customer添加一个构造函数或属性,它接受Person并将值赋给基类,例如

public Customer(Person person)
{
    base.Name = person.Name;
    base.Address = person.Address;
}

或者我可以像这样实现一个不整洁的set访问器:

public Person Person
{
    set
    {
        Name = value.Name;
        Address = value.Address;
    }
}

或者我可以像这样将Person聚合到客户中:

public class Customer
{
    public Person Person { get; set; }
    public string CustomerNumber { get; set; }
    public string PaymentTerms { get; set; }
}

最后一个对我来说是最好的,除了总是不得不访问Customer.Person.Name,而不只是Customer.Name

2 个答案:

答案 0 :(得分:5)

我个人会去作曲,是(你的最后一个选择)。请注意,您始终可以提供“帮助属性”:

public string Name { get { return Person.Name; } }

实际上,您可以为所需的所有属性执行此操作,并且永远不会将Person属性公开给外部世界。

另一方面,如果您希望能够将Customer视为Person,则继承 非常有用 - 将其传递给Person的方法例如,参数。我通常通过接口完成那种事情;您可以IPersonCustomer同时实施Person界面。继承引入了各种各样的设计决策,当你没有进行继承时,它们根本就没有出现(或者更简单)。

答案 1 :(得分:4)

我要么使用构造函数,要么使用工厂方法,比如

public static Customer CreateFromPerson(Person person)
{
    return new Customer(){ Name = person.Name }//etc...
}

我不喜欢这个setter,因为你实际上并没有在客户上设置'Person',我不喜欢最后一个选项,因为当你访问该人时会导致Law of Demeter (LOD)违规通过客户(customer.person.name等)。