Ответ 1
Основная идея SPECIFICATION заключается в том, что это предикат, который часто подразумевает использование с ним логических операторов
СПЕЦИФИКАЦИЯ - это адаптация установленного формализма (Eric Evans DDD, стр. 274)
Например, мы можем сказать, что поле красного цвета, то есть удовлетворяет некоторой RedSpecification. Мы можем объявить некоторые GreenSpecification и даже составные RedOrGreenSpecification. Если у нас есть расширенная инфраструктура, поддерживающая логические операции для спецификаций, это может быть что-то вроде
BoxSpecification redBoxSpec = BoxSpecification.forColor(BoxColor.RED);
BoxSpecification greenBoxSpec = BoxSpecification.forColor(BoxColor.GREEN);
BoxSpecification redOrGreenBoxSpec = redBoxSpec.or(greenBoxSpec);
то мы можем использовать спецификацию, например, для запроса всех красных/зеленых ячеек из некоторого репозитория:
Collection<Box> boxes = boxRepository.findAll(redOrGreenBoxSpec);
Что касается POLICY - это вариант шаблона STRATEGY, но его основной целью является инкапсуляция бизнес-правил в какую-то декларативную форму.
Технически - это не всегда прямая реализация СТРАТЕГИИ - на первых этапах это может быть просто отдельный класс (как показано в первой главе синей книги), но его можно легко расширить позже
Политика - это другое название шаблона проектирования, известного как СТРАТЕГИЯ. Обычно это мотивируется необходимостью замены различных правил, которые нам не нужны, насколько нам известно. Но концепция, которую мы пытаемся захватить, вписывается в смысл политики, которая является одинаково важной мотивацией в доменном дизайне
Например, мы упаковываем подарки в желтые ящики в январе, а в красных ящиках в феврале
public class Box{
public BoxColor getColor(){}
public void recolor(BoxColor color){}
}
public class BoxFactory{
public Box createDefaultBox(SomeDate date){
NewBoxPolicy boxPolicy = PolicyRegistry.getNewBoxPolicyForDate(date);
Box box = new Box();
boxPolicy.prepareBox(box);
return box;
}
}
public interface NewBoxPolicy{
void prepareBox(Box box);
}
public class FebruaryNewBoxPolicy implements NewBoxPolicy{
public void prepareBox(BoxBox) { box.recolor(BoxColor.RED}; }
}
public class JanuaryNewBoxPolicy implements NewBoxPolicy{
public void prepareBox(BoxBox) { box.recolor(BoxColor.YELLOW}; }
}
public class PolicyRegistry{
public static NewBoxPolicy getNewBoxPolicyForDate(SomeDate date){
switch (date.month()){
case SomeMonth.JANUARY: return JANUARY_NEW_BOX_POLICY;
case SomeMonth.FEBRUARY: return FEBRUARY_NEW_BOX_POLICY;
default: throw new AssertionError();
}
}
Важно понимать, что POLICY может инкапсулировать действия, тогда как SPECIFICATION описывает только свойства объекта (эти свойства могут удовлетворять или НЕ удовлетворять бизнес-требованиям). Некоторая проверка ПОЛИТИКА может использовать СПЕЦИФИКАЦИИ, чтобы проверить, что требования выполнены, конечно.
Таким образом, у вас может быть много разных экземпляров SPECIFICATION в вашем проекте, и они могут описывать как действительные, так и недопустимые объекты с бизнес-точки зрения. Фактически, спецификации не имеют никакого смысла: например, если у вас есть сайт для поиска продукта, пользователь может указать запрос на поиск продукта под названием "XBOX", но с именем производителя "Sony", если знание о том, что только конкретные производители могут производить определенные продукты, которые не учитываются в вашей модели.
Важным аспектом Политики является то, что ее целью является инкапсуляция фактических бизнес-правил (поэтому код не разбросаны по разным частям проекта), поэтому при изменении правил вы можете легко найти соответствующий класс. Таким образом, у вас может быть много СПЕЦИФИКАЦИЙ в вашем проекте, но управляемое количество ПОЛИТИКИ, и эти ПОЛИТИКИ должны быть легко найти и изменить.
P.S. обратите внимание, что этот пост - всего лишь пример, а не лицензия на чрезмерную разработку, конечно, вы должны использовать простейший дизайн, это вопрос здравого смысла.