Объектно-ориентированные рекомендации - Наследование v Композиция v Интерфейсы - PullRequest
39 голосов
/ 19 октября 2008

Я хочу задать вопрос о том, как бы вы подошли к простой объектно-ориентированной задаче проектирования. У меня есть несколько собственных идей о том, как лучше всего решить этот сценарий, но мне было бы интересно услышать некоторые мнения от сообщества Stack Overflow. Ссылки на соответствующие статьи онлайн также приветствуются. Я использую C #, но вопрос не зависит от языка.

Предположим, я пишу приложение для видеомагазина, база данных которого имеет таблицу Person с полями PersonId, Name, DateOfBirth и Address. Он также имеет таблицу Staff, которая имеет ссылку на PersonId, и таблицу Customer, которая также ссылается на PersonId.

Простой объектно-ориентированный подход состоит в том, чтобы сказать, что Customer "является" Person, и, следовательно, создавать классы примерно так:

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer : Person {
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff : Person {
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}

Теперь мы можем написать функцию скажем, чтобы отправлять электронные письма всем клиентам:

static void SendEmailToCustomers(IEnumerable<Person> everyone) { 
    foreach(Person p in everyone)
        if(p is Customer)
            SendEmail(p);
}

Эта система работает нормально, пока у нас не появится кто-то, кто будет и клиентом, и сотрудником. Предполагая, что мы не хотим, чтобы в нашем списке everyone был один и тот же человек дважды, один раз как Customer и один раз как Staff, мы делаем произвольный выбор между:

class StaffCustomer : Customer { ...

и

class StaffCustomer : Staff { ...

Очевидно, что только первый из этих двух не нарушит функцию SendEmailToCustomers.

Так что бы вы сделали?

  • У класса Person есть необязательные ссылки на классы StaffDetails и CustomerDetails?
  • Создать новый класс, содержащий Person, плюс необязательные StaffDetails и CustomerDetails?
  • Сделать все интерфейсом (например, IPerson, IStaff, ICustomer) и создать три класса, которые реализовали соответствующие интерфейсы?
  • Есть другой совершенно другой подход?

Ответы [ 12 ]

1 голос
/ 19 октября 2008

Мы изучали эту проблему в колледже в прошлом году, мы изучали eiffel, поэтому мы использовали множественное наследование. В любом случае альтернатива ролям Foredecker кажется достаточно гибкой.

0 голосов
/ 16 июля 2013

Вы, вероятно, не хотите использовать наследование для этого. Попробуйте вместо этого:

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer{
    public Person PersonInfo;
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff {
    public Person PersonInfo;
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...