Выбор стратегии

 
 
 
Сообщения:298
Наверняка все встречались с ситуацией, когда есть пачка стратегий, надо выбрать одну и использовать ее.

Проблемы начинаются когда для условия выбора стратегии становятся достаточно сложными.

В таком случае у нас частенько можно встретить интерфейсы типа:

interface Strategy<I, R> {
   R perform(I i);
   boolean isApplicable(I i);
}

Каждая стратегия сама решает для какого аргумента она подходит, а для какого - нет.

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

Ломаю голову, как это можно зарефакторить, у кого как подобная задача решается?

"Мы же профессионалы! Мы всегда делаем чуть больше, чем требуется!" (с)
 
 
Сообщения:9915
MuH3gPaB:
если несколько стратегий применимы - может выбраться не та.
Может даже если стратегия технически подходит - придраться к чему-то еще в объекте, чтоб таки отсеить ненужные стратегии?

На данный момент задача звучит слишком абстрактно. Если бы ты описал настоящие стратегии было бы проще что-то подсказать.
 
 
Сообщения:298
Староверъ:
Может даже если стратегия технически подходит - придраться к чему-то еще в объекте, чтоб таки отсеить ненужные стратегии?

Тогда при создании новой стратегии надо смотреть на все остальные, нет ли пересечений, что тоже не очень удобно.

Пример, допустим, стратегия обработки оплаты заказа.
interface PaymentStrategy<Order, PaymentResult> {
   PaymentResult perform(Order order);
   boolean isApplicable(Order order);
}

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

"Мы же профессионалы! Мы всегда делаем чуть больше, чем требуется!" (с)
Изменен:28 дек 2019 09:15
 
 
Сообщения:9915
Ну ты уж выбирай - либо сортировать их, либо делать так чтоб не было пересечений :) Вообще код менее абстрактным не стал - я имел в виду рассказать про парочку стратегий, например, тех что пересекаются.
 
 
Сообщения:298
Староверъ:
Ну ты уж выбирай - либо сортировать их, либо делать так чтоб не было пересечений :)

А хочется и на елку влезть и... новый год же! =)

Еще более конкретный пример для пересечения стратегий.
Допустим тот же интерфейс с платежами.

1. Пользователь размещает заказ, добавляет кредитку и платит ей. Его редиректит на 3DSecure и обратно на сайт.
boolean isApplicable(Order order) {
   order.paymentMode == CREDIT_CARD;
}


2. Пользователь звонит на горячую линию, диктует заказ и оплачивает кредиткой, которая сохранена в системе. В этом случае 3DSecure не требуется.
boolean isApplicable(Order order) {
   order.paymentMode == CREDIT_CARD && order.channel == PHONE;
}


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

"Мы же профессионалы! Мы всегда делаем чуть больше, чем требуется!" (с)
 
 
Сообщения:9915
Ну я в общем за то чтоб добавить доп условие в 1ую стратегию. Это же не правда на самом деле что она подходит если чел звонит по телефону. Я б делал что-то вроде:

boolean isApplicable(Order order) {
   order.paymentMode == CREDIT_CARD && order.channel == WEBSITE;
}
Изменен:28 дек 2019 11:50
 
 
Сообщения:298
Ну собственно пока так и делаем =)

Просто ищу как такую логику можно зарефакторить. Вдруг есть какое-то элегантное решение, о котором я не догадываюсь.

"Мы же профессионалы! Мы всегда делаем чуть больше, чем требуется!" (с)
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет