У меня есть класс Java, как показано ниже
class MyClass {
public boolean rule1() {...}
public boolean rule2() {...}
public boolean rule3() {...}
}
теперь, например, я хочу проверить правило выше класса во многих отношениях, таких как:
MyClass myClass = new MyClass();
if (myClass.rule1() && myClass.rule2 || myClass.rule3) {}
и теперь мне интересно, как я могу реализовать вышеприведенную строку, как эта?
if (myClass.rule1().and().rule2().or().rule3().accept()) {}




Взгляните на Predicate<T> и его and или or.
MyClass instance = new MyClass();
Predicate<MyClass> predicate = MyClass::rule1;
if (predicate.and(MyClass::rule2).or(MyClass::rule3).test(instance)) {
// todo
}
Это может выглядеть менее читабельно, чем версия, которую вы упомянули, переименование MyClass во что-то более осмысленное поможет. Если это не работает для вас, подумайте о том, чтобы написать Builder . Хорошие комплексные примеры, которые можно найти, скажем, в сборщиках динамических SQL (например, jooq).
Более чистым способом было бы использование функционального интерфейса Predicate:
Параметры типа:
T - тип входа в предикат Functional Интерфейс: это функциональный интерфейс, поэтому его можно использовать как цель назначения для лямбда-выражения или ссылки на метод.
public class A {
public Predicate rule1() {
return //some operation that returns a boolean;
}
public Predicate rule2() {
return //some operation that returns a boolean;
}
public Predicate rule3() {
return //some operation that returns a boolean;
}
}
Но цепочка вызовов методов if выглядела бы не так, как вы ищете, а именно:
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
В противном случае вам пришлось бы реализовать шаблон Builder, а также реализовать методы and(), or() и accept. Например:
public class BooleanEvaluator {
List<String> rules = new ArrayList<>();
public BooleanEvaluator and() {
rules.add("&&");
return this;
}
public BooleanEvaluator or() {
rules.add("or");
return this;
}
public boolean accept() {
int i = 0;
boolean result = Boolean.parseBoolean(rules.get(0));
while (i < rules.size() - 1) {
if (rules.get(i).equals("&&")){
result = result && Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
else if (rules.get(i).equals("||")){
result = result || Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
}
return false;
}
public BooleanEvaluator rule1() {
boolean result = // apply the rule 1
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule2() {
boolean result = // apply the rule 2
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule3() {
boolean result = // apply the rule 3
rules.add(String.valueOf(result));
return this;
}
void some_method(){
if (this.rule1().and().rule2().or().rule3().accept()) {
// ...
}
}
}
Естественно, метод accept должен быть намного надежнее, это просто показать, как будет выглядеть дизайн.
Вы не ошиблись, я бы сказал, что это гораздо менее читаемый способ сделать это, чем исходный код.