Java: использование полиморфизма, чтобы избежать операторов if?
===============================================================

Я пытаюсь написать Java-программу, которая инициализирует определенные макеты на основе того, что выбирает пользователь. То, что я хочу сделать, это попытаться избежать написания нескольких операторов if, чтобы код можно было масштабировать для будущего использования, если потребуется добавить больше макетов. Я слышал, что лучший способ реализовать это - использовать полиморфизм, но мое понимание полиморфизма все еще немного размыто.

Скажем, я хочу реализовать этот случай:

Я думал о создании интерфейса для реализации классов. Что меня смущает, так это то, как он работает в main (). Разве мне не понадобится условный оператор if или switch, чтобы выяснить, какой класс создать?

Тогда где-то в основном:

Разве мне не потребовалось бы переключателя или оператора if в основной программе, чтобы выяснить, какой макет выбрал пользователь во время выполнения?

Спасибо!

Как правило, в какой-то момент будет трудно избежать какого-либо условного выражения для создания экземпляра соответствующего класса.

Преимущество полиморфизма возникает, когда у вас есть несколько операторов if-else в нескольких местах. Полиморфизм заключает в себе условную логику для вас. Увидеть[этот вопрос](https://stackoverflow.com/questions/1166078/what-is-this-code-smell-called) для некоторых других дискуссий на эту тему.

Этот вид рассеянной логики:

Заменяется на что-то более простое:



Поскольку у java нет функций первого класса, вы можете использовать интерфейсы для обхода.



Что-то где-то нужно указать реализацию. Это может быть цепочка операторов if в исходном коде, но это может быть и нечто другое; например, имя класса, указанное во внешнем источнике данных, созданное с помощью отражения.

Для некоторых интерфейсов может быть гораздо больше обращений к интерфейсу, чем к экземплярам. Полиморфизм можетуменьшить привязка к конкретным реализациям.

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



Нет. Используйте карту. Когда у вас есть выбор, просто посмотрите на обработчик на карте и начинайте.

psuedocode

только одно утверждение.



Вы должны использовать фреймворк, чтобы избежать создания образа для определения поведения.

Весна позволяет нам справиться и решить эту проблему. Это использует фабричный образец и больше образцов дизайна. Таким образом, используя аннотации или файл конфигурации xml, вы можете решить, какие классы создавать. П.Д .: Конечно, я на 100% уверен, что весна использует if. Но это доказано и используется во многих сильных и надежных приложениях.



Я немного размыт в вашей архитектуре кода, но идея в том, что у вас есть только переключатель водин вместо того, чтобы разбросать по всему коду несколько переключателей с одинаковыми точными сигнатурами функций, кроме объекта, над которым он работает.

Точная реализация зависит от ваших целей, но я думаю, что у вас будет один класс, реализующий LayoutHander и имеющий ссылку на член Layout. Когда пользователь выбирает свой макет, полиморфизм овладевает ЗДЕСЬ, а не уровнем выше, как у вас сейчас. То есть, если объект, который определяет другое поведение, является «Layout», то вам нужно сделать Layout полиморфным, а не LayoutHander.

Когда вы думаете о полиморфизме, подумайте о повторном использовании кода. «Какой общий набор функций имеют эти взаимосвязанные, но разные объекты разделяют?»



Я думаю, что использование if-операторов для инициализации нормально. Вы пытаетесь избежать повторного использования операторов if для «выбора» поведения во всей программе. Использование if-операторов один раз для инициализации нормально.

Конечно, есть и способы избежать даже этих if-операторов инициализатора, но вы должны решить, какой уровень сложности и возможная потеря читаемости подходят для вашего приложения.

Например, вот несколько подходов к этой проблеме от простого к более сложному:

использовать эти инициализаторы if-операторовиспользует жестко запрограммированные ссылки для реализации классов непосредственно в логике программы (сложнее найти)инициализировать некоторую структуру данных (например, Map) с возможными классами реализациивсе еще жестко запрограммированные ссылки на реализацию классовкак правило, проще добавить больше реализующих классовкод немного сложнее и абстрактнее для понимания и отладкииспользовать динамическую регистрациюнет жестко запрограммированных ссылок на классы реализации в приложениитребуется дополнительная настройкакод сложнее понять, не зная, как работает регистрацияХороший пример последнего метода (динамическая регистрация) - посмотреть, как работает JDBC. Драйверы JDBC регистрируются в приложении с помощью`Class.forName()` и затем конкретный драйвер JDBC выбирается с использованием URL-адреса JDBC. Вот типичный рабочий процесс:

Потенциальные целевые драйверы JDBC добавляются classpath.

Приложение настроено со списком этих драйверов, например, перечисляя драйверы JDBC в файле свойств.

Приложение инициализируется по телефону`Class.forName()` на каждого водителя в списке. Каждый драйвер знает, что нужно зарегистрироваться в DriverManager, когда он загружается`Class.forName()`

Приложение определяет, какой целевой ресурс базы данных использовать, и разрешает его в URL JDBC, например, в диалоговом окне конфигурации или в приглашении пользователя.

Приложение запрашивает у DriverManager соединение на основе целевого URL JDBC. DriverManager опрашивает каждый зарегистрированный драйвер, чтобы определить, может ли он обрабатывать целевой URL JDBC, пока DriverManager не найдет тот, который работает.

Это было бы противоположной крайностью, чтобы избежать этих if-утверждений.



«... для будущего использования, если нужно добавить больше макетов»

Я бы также посоветовал вам посмотреть на заводскую модель. Если вы используете эту условную логику на фабрике, она должна помочь в обслуживании и удобочитаемости.



Короче да. Вам понадобится ifs или какой-нибудь картограф.

Вам понадобится какой-то способ преобразовать ввод пользователя в класс, который вы хотите. Ifs, которые есть в вашем коде, будет работать нормально, быть понятным и читабельным. Вы также можете использовать переключатель.

Этого можно избежать, но в конечном итоге вы запутаете свой код, и в конце концов, вероятно, все равно будет что-то вроде if. Вы должны определить отображение от пользовательского ввода до объекта; это не может быть обойдено. Самый ясный и наиболее приемлемый способ сделать это - то, что у вас уже есть (хотя я бы добавил еще ifs там. :))

Идея, что у вас есть разные классы для каждого макета, неплоха. Это очень похоже на концепцию[класс черт](https://en.wikipedia.org/wiki/Traits_class), Посмотри на это тоже. Это будет полезно для вашего дизайна.