Действительно ли для преобразования объекта из базового класса в подкласс
В моем приложении на данный момент у меня (как и во многих других приложениях) объект под названием Contact
, который представляет любого человека. На самом базовом уровне это используется для представления деловых контактов. Однако он также может использоваться для представления сотрудников компании. и есть также несколько специальных типов сотрудников (скажем, есть один под названием Manager
)
Я пытаюсь моделировать это как отношение наследования, которое имеет смысл. Сотрудники имеют имена и адреса, как и контакты, а также ряд атрибутов, связанных с занятостью. Менеджеры также имеют несколько специфических для менеджера атрибутов.
Трудность возникает, когда работник получает повышение до менеджера. Можно ли преобразовать базовый класс Employee
в наследующий класс Manager
? Он чувствует себя не так. Думаю, я сделал бы это со специализированным конструктором на Manager
.
Как в стороне NHibernate поддерживает такое поведение? это так же просто, как получение сотрудника, создание менеджера из сотрудника, а затем сохранение менеджера?
Ответы
Ответ 1
Пока ваша бизнес-модель соответствует вашему домену, вы поступаете правильно.
Однако мне кажется, что у вас должно быть что-то вроде:
Manager Promote(Employee employee)
{
var manager = new Manager();
//promote your employee to a manager here
return manager;
}
внутри некоторого процесса рабочего процесса.
Что касается NHibernate, похоже, что вы смешиваете логику ORM с вашим бизнес-доменом. Продвижение сотрудника к менеджеру является конструкцией бизнес-домена и, как таковой, относится к вашей бизнес-модели. Однако, как NHibernate отображает ваших сотрудников и ваших менеджеров в вашу БД, это не имеет ничего общего с вашей бизнес-моделью, за исключением того, как их сопоставить. Это определенно не имеет никакого отношения к тому, как продвигать сотрудника к менеджеру.
Ответ 2
В этом случае я бы пошел с составом над наследованием. Если вы придерживаетесь наследования, вы будете менять классы с каждой рекламой или понижением, и каждый раз, когда вы нанимаете контакт или сотрудник уходит и становится постоянным контактом.
Легче сказать, что у контактов есть роли. Вы можете добавить роль менеджера в контакт для его продвижения и удалить роль, чтобы ее запустить.
Ответ 3
Я бы лично имел базовый класс со всеми основными вещами в нем и списком ролей.
Каждая роль обладает собственными свойствами и функциональными возможностями.
Преимущества в два раза:
- Легко дать или взять роль/от человека
- Это позволит вашим людям иметь несколько ролей без необходимости создавать "комбинированные классы"
Если вы идете с одиночным наследованием, идущим с наследованием, в ближайшее время вы получите такие классы, как "ManagerProgrammer", "ProgrammerStockManager", "ProgrammerSupport"
Ответ 4
Да, это действительно. Что касается реализации, вы можете использовать:
- Статический метод для Менеджера:
public static Manager Promote(Employee employee) { ... }
- Специализированный конструктор в Менеджере
- Factory или класс обслуживания
Я думаю, что любой из этих подходов был бы хорошим решением. Лично мне нравится специализированное конструкторское решение, так как оно хорошо отражает реальный мир: вы создаете нового менеджера из существующего сотрудника.
Ответ 5
G'day,
Если вы обнаружите, что вам нужно преобразовать производный класс из одного типа в другой производный тип, то это запах, который имеет исходный проект.
Мне кажется, что вы неправильно представляете объект менеджера.
Вернитесь к основам и подумайте в терминах OO, где ваш базовый класс (Contact) содержит общие элементы объектов Employee и Manager. Любые производные объекты являются только специализациями базового класса.
В этом случае не является Менеджером экземпляр сотрудника?
Оба класса Manager и Employee должны иметь член данных reportsTo, который также имеет тип Employee.
Единственное различие, которое я могу видеть на данный момент, состоит в том, что объект-менеджер теперь имеет коллекцию объектов Employee, которые являются их собственными directReports. Вероятно, это должно быть реализовано как указатель на контейнер объектов Employee.
Я не могу думать о какой-либо специализации в поведении, которая требует выделения объекта Employee из объекта Manager.
Хммм, возможно, создайте базовый класс Person, который содержит в нем контактные данные.
Изменить: Извините, из вашего комментария, я думаю, я был недостаточно ясен. То, что я описал, не приводит к двум отдельным классам, которые непосредственно получены из вашего класса Contact, так что вам нужно изменить экземпляр Employee Manager во время выполнения, что было вашим исходным вопросом.
То есть я не думаю, что у вас должны быть два производных класса, Employee и Manager, непосредственно наследуемые от вашего класса Contact.
Разве оба этих типа людей не работают на предприятии? Зачем различать Manager и Employee? Является ли сотрудник больше не Работником, если он становится Менеджером?
Имея два производных класса, Менеджер и Сотрудник, полностью ошибочно ИМХО. Вы пробовали ломать дело в терминах "isa" и "имеет" отношения. Затем вы можете видеть, что ваша основная структура неверна.
Говорить Сотрудник "isa" Контакт просто не имеет смысла. Скорее всего, "Сотрудник" isa "Человек и лицо" имеет "набор контактных данных".
Может быть, получить класс Менеджера в качестве специализации сотрудника? Сотрудник "isa" Person. Менеджер "isa" Сотрудник, который "isa" Person.
НТН
веселит,
Ответ 6
Контакт - это атрибут Employee. Работник (ваш сотрудник) - это роль, роль менеджера. Работник и менеджер - все еще Сотрудник, но имеют Роли. Роль - это отношение IS IN, Employee - отношение AM A, а Contact - отношение HAS A.
Сотрудник имеет контакт (отношения 1-1) Один контакт для каждого сотрудника (1-М, если у них есть два телефона и т.д., Но я отвлекаюсь)
Сотрудник IS IN Role (отношения M-M) Многие сотрудники много ролей
Employee Is A (M-1 relatiohship) - Многие сотрудники, все сотрудники.
Итак, вы меняете роли.