У меня есть класс, используемый для обработки платежей клиентов. Все методы этого класса, кроме одного, одинаковы для каждого клиента, за исключением одного, который вычисляет (например), сколько должен пользователь пользователя. Это может сильно варьироваться от клиента к клиенту, и нет простого способа записать логику вычислений в нечто вроде файла свойств, поскольку может быть любое количество пользовательских факторов.
Я мог бы написать некрасивый код, который переключается на основе customerID:
switch(customerID) {
case 101:
.. do calculations for customer 101
case 102:
.. do calculations for customer 102
case 103:
.. do calculations for customer 103
etc
}
но это требует восстановления класса каждый раз, когда мы получаем нового клиента. Какой способ лучше?
[Править] «Дубликат» статьи совершенно другой. Я не спрашиваю, как избежать оператора switch, я спрашиваю о современном дизайне, который лучше всего подходит для этого случая - который я мог бы решить с помощью оператора switch, если бы я хотел написать код динозавра. Приведенные здесь примеры являются общими и бесполезными, поскольку по сути они говорят: «Эй, коммутатор работает довольно хорошо в некоторых случаях, а не в других».
[Править] Я решил использовать самый лучший ответ (создать отдельный класс «Клиент» для каждого клиента, который реализует стандартный интерфейс) по следующим причинам:
Согласованность: я могу создать интерфейс, который гарантирует, что все классы Customer получают и возвращают один и тот же вывод, даже если он создан другим разработчиком
Поддержка: весь код написан на одном и том же языке (Java), поэтому больше нет необходимости изучать отдельный язык кодирования, чтобы поддерживать то, что должно быть очень простой функцией.
Повторное использование: в случае возникновения подобной проблемы в коде я могу повторно использовать класс Customer для хранения любого количества методов для реализации «пользовательской» логики.
Знакомство: я уже знаю, как это сделать, поэтому я могу сделать это быстро и перейти к другим, более актуальным вопросам.
Недостатки:
Каждому новому клиенту требуется компиляция нового класса Customer, что может усложнить процесс компиляции и развертывания изменений.
Каждый новый клиент должен быть добавлен разработчиком - специалист по поддержке не может просто добавить логику в нечто вроде файла свойств. Это не идеально ... но тогда я также не был уверен, как специалист службы поддержки сможет выписать необходимую бизнес-логику, особенно если она сложна со многими исключениями (что вполне вероятно).
Это не будет хорошо масштабироваться, если мы добавим много-много новых клиентов. Этого не ожидается, но если это произойдет, нам придется переосмыслить многие другие части кода, а также этот.
Для тех, кто заинтересован, вы можете использовать Java Reflection для вызова класса по имени:
Payment payment = getPaymentFromSomewhere();
try {
String nameOfCustomClass = propertiesFile.get("customClassName");
Class<?> cpp = Class.forName(nameOfCustomClass);
CustomPaymentProcess pp = (CustomPaymentProcess) cpp.newInstance();
payment = pp.processPayment(payment);
} catch (Exception e) {
//handle the various exceptions
}
doSomethingElseWithThePayment(payment);