Это мой первый пост, так что будьте добры. Это вопрос интервью, который я недавно получил, но не смог найти ответ после поиска (Google, C ++ FAQ и т. Д.).
Есть интерфейс I1 с поведением b1 (). Есть 3 класса A, B, C. Все эти классы реализуют интерфейс I1 путем переопределения b1 (). Существует четвертый класс D, который имеет поведение (b1), определенное в интерфейсе I1, и дополнительное поведение b2
Вопрос в том, как вы проектируете класс D.
Мой ответ состоял в том, чтобы создать еще один интерфейс I2, который определяет поведение b2 (), и заставить класс D реализовать как I1, так и I2 (множественное наследование в C ++) путем переопределения обоих b1 () и b2 ()
Интервьюер согласился с решением, но спросил, что если в будущем появятся новые классы с новым набором поведений, как мы справимся с этим
Я мог только подумать о добавлении большего количества интерфейсов (I3, I4 и т. Д.) И выполнении множественного наследования, но я знаю, что здесь вы в конечном итоге получаете огромное количество производных классов с соответствующими интерфейсами
Интервьюер, казалось, ожидал лучшего решения, но не дал ответа. Я хотел бы знать, как эксперты решат эту проблему дизайна.
PS: После серьезного размышления об этом, я думаю, что ответ может заключаться в использовании шаблона проектирования, но, глядя на общие шаблоны проектирования, я не смог найти ни одного, соответствующего этой проблеме
edit 1: У меня есть еще вопросы и разъяснения, поэтому редактирую пост здесь, не уверен, что это правильный путь, или мне нужно опубликовать это как ответ на мой собственный вопрос.
Сначала позвольте мне поблагодарить @Nawaz, @Alexandre и @Sjoerd за ваш ценный вклад. Я только начинаю изучать аспекты проектирования в C ++ / шаблонах проектирования, поэтому извините за незнание этого вопроса.
Пример паттерна Vistor от @Nawaz был действительно полезным, но я думаю, что это только частный случай исходной проблемы, заданной интервьюером. @ Александр правильно указал сценарии здесь.
Позвольте мне объяснить еще один аспект этого.
Когда мы говорим о поведении, нам нужно сгруппировать их на основе
1) распространенное поведение, связанное с группой объектов или объектом. (Это интуитивно понятно или можно наблюдать как в реальном мире)
Например: поведение Чувака (на примере @Nawaz) - я гуляю, ем, учусь и т. д.
2) необычное или очень своеобразное поведение, связанное с группой (это противоречит интуиции)
Например: просто ради аргумента, рассмотрим Чувак, который сочиняет музыку (я знаю, этот пример не идеален)
3) совершенно не связанное с группой поведение. Я не могу придумать пример, но я хочу сказать, что по какой-то странной причине нам нужно придать объекту такое поведение.
Так что я думаю, что шаблон посетителя может решить проблему в 1), но я подозреваю, что он не подходит для 2) и 3).
Если взять пример IDude, нам потребуются следующие изменения, чтобы создать Чувака, который может сочинять музыку.
class IComposerBehavior;
class IComposer
{
public:
virtual ~IComposer() {}
virtual void accept(IComposerBehavior *behaviour) = 0 ;
};
class IComposerBehavior
{
public:
virtual ~IComposerBehavior() {}
virtual void visit(IComposer * ) = 0;
};
class Dude : public IDude, public IComposer
{
public:
virtual void accept(IDudeBehavior *behaviour)
{
behaviour->visit(this);
}
virtual void accept(IComposerBehavior *behaviour)
{
behaviour->visit(this);
}
};
class SymphonyComposerBehavior : public IComposerBehavior
{
public:
virtual void visit(IComposer *dude) { cout << "Dude is composing a symphony" << endl; }
};
Точно так же нам нужно изменить код клиента также для учета SymphonyComposerBehavior.
Таким образом, в итоге мы изменили и код класса Dude, и код клиента, что сводит на нет влияние шаблона.
Я думаю, что интервьюер спрашивал о новом поведении, которое нельзя отнести к группе связанных поведений, которые были ранее идентифицированы. Таким образом, в этом случае, даже если классы являются фиксированными, шаблон посетителя может решить, как указал @Alexandre?
Позвольте мне привести пример только в верхней части моей головы (не уверен, что это правильный пример для представления проблемы). Допустим, мне нужно разработать приложение для фирмы-производителя роботов. Требование постепенно растет как
- Initially We are only producing Toy Robots
- Then Human helper Robots
- Then Self Healing Robots (would just correct itself when defective)
- Then Humanoid Robots
- Then machine Robots (that are not human like but as a substitute for any machine you can think of) . I have deliberately put this here even though its place should be before with a correct evolution scheme.
- finally Humanoid Robots with life (atleast we can dream :-) )
Так что, если мы знаем полный список роботов до разработки приложения, мы могли бы придумать лучший дизайн,но как мы проектируем, когда каждый новый тип вводится последовательно в указанном выше порядке.Суть в том, что мы знаем, что у робота есть определенное поведение или характеристики, но когда нам нужно внедрить необычные функции (например, самоисцеление, робот-машина), как мы поступим?
Спасибо.