Я хочу задать вопрос о том, как бы вы подошли к простой объектно-ориентированной задаче проектирования. У меня есть несколько собственных идей о том, как лучше всего решить этот сценарий, но мне было бы интересно услышать некоторые мнения от сообщества 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
) и создать три класса, которые реализовали соответствующие интерфейсы?
- Есть другой совершенно другой подход?