Я не могу найти лучшее решение моей проблемы. У меня есть контроллер представления, который представляет список элементов. Эти элементы являются моделями, которые могут быть экземплярами B, C, D и т. Д. И наследоваться от A. Таким образом, в этом контроллере представления каждый элемент должен переходить на другой экран приложения и передавать некоторые данные, когда пользователь выбирает один из них. , Мне приходят на ум две альтернативы (пожалуйста, игнорируйте синтаксис, это не конкретный язык)
1) переключатель (я знаю, что отстой)
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
switch(a.type) {
case b:
B b = (B)a;
go to screen X;
x.v1 = b.v1; // fill X with b data
x.v2 = b.v2;
case c:
go to screen Y;
etc...
}
}
2) полиморфизм
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
Screen s = new (a.getDestinationScreen()); //ignore the syntax
s.v1 = a.v1; // fill s with information about A
s.v2 = a.v2;
show(s);
}
//inside B
Class getDestinationScreen(void) {
return Class(X);
}
//inside C
Class getDestinationScreen(void) {
return Class(Y);
}
Моя проблема с решением 2 состоит в том, что, поскольку B, C, D и т. Д. Являются моделями, они не должны знать о вещах, связанных с просмотром. Или они должны в этом случае?
источник
Скорее комментарий, чем ответ, но я думаю, что это бросок. Либо Посмотреть должен знать все о модели , чтобы он мог выбрать экран (переключатель) или модель должна знать все о представлении , так что можно выбрать экран (полиморфизм). Я думаю, что вы должны выбрать то, что, по вашему мнению, будет самым простым с течением времени; нет правильного ответа на вопрос. (Я надеюсь, что кто-то может доказать, что я неправ.) Я действительно склоняюсь к полиморфизму, сам.
Я столкнулся с этой проблемой немного. Самым раздражающим случаем был класс Wanderer, экземпляры которого бродили по карте. Чтобы нарисовать его, либо дисплей должен был знать о Wanderer, либо Wanderer должен был знать о дисплее. Проблема была в том, что было два дисплея (и еще больше). Поскольку число различных подклассов Wanderer было большим и растущим, я поместил код для рисования в подклассы Wanderer. Это означало, что у каждого большого класса был ровно один метод, который должен был знать о Graphics2D, и ровно один метод, который должен был знать о Java3D. Некрасиво.
В итоге я разделил класс, дав мне две параллельные классовые структуры. Класс Wanderer был освобожден от знаний о графике, но классу DrawWanderer по-прежнему нужно было знать о Wanderer больше, чем было прилично, и ему нужно было знать о двух (и, возможно, более) совершенно разных графических средах (представлениях). (Я полагаю, что эта идея расщепления класса может быть своего рода ответом, но все, что она действительно делает, это немного сдерживает проблему.)
Я думаю, что это очень общая и фундаментальная проблема объектно-ориентированного проектирования.
источник
Я думаю, что использование переключателя - лучший вариант, чем использование полиморфизма для этого случая.
Это довольно простая вещь, поэтому я не думаю, что это может быть слишком сложно при использовании полиморфизма.
Я хотел бы отметить в этом сообщении в блоге . Операторы Switch не обязательно безобразны, если вы правильно их используете. И в вашем случае, абстрагирование таких моделей для использования в контроллере может быть излишним и может привести к нежелательным результатам. Вроде нарушает СРП.
источник
Я согласен с этой проблемой. Я также немного обеспокоен тем, что объекты, которые находятся в выпадающем списке, будут иметь поведение. Я не уверен, что это «плохая вещь», никогда не делавшая этого, это просто кажется мне неестественным выбором.
Кроме того, это не похоже,
A
и это подклассы, с которыми у вас есть интересный полиморфизм. Интересный тип на самом делеScreen
. В этом примереA
это просто класс, содержащий информацию дляScreen
создания информации.Если вы сделаете так, чтобы в выпадающем списке содержался список всех
a.type
возвращаемых значений, оператор switch кажется более естественным. Однако вместо того, чтобы поместить это прямо в обработчик события click, я бы поместил его вScreenFactory
. Тогда у вас есть:Это позволяет вам протестировать поведение построения экрана и приятно вытянуть некоторые функциональные возможности из вашего пользовательского интерфейса. Он сохраняет ваши слои View без изменений. Возможно, это упрощает ваш дизайн, если это означает, что
A
подклассы можно свернуть вtype
флаг, который они содержат.источник