Замените if / else в определенном порядке на надлежащий дизайн (основанный на правилах / приоритете if / else)

#algorithm #oop #design-patterns #data-structures

#алгоритм #ооп #дизайн-шаблоны #структуры данных

Вопрос:

У меня есть метод класса, который реализует логику, основанную на правилах. Структура выглядит следующим образом:

 sub process {  
   # declarations etc    
   # other code     
   # core logic:    
   if($conditions->{size} == $item_size) {  
     #do something here as it matches the rule based on size
     return $resu<  
     }  

     if($conditions->{area} == $item_area_dispatch) {  
      #do something that matches the area criteria
      return $resu<  
      }   

      if($conditions->{country} == $item_country) {  
      #do something that matches the country criteria   
      return $resu<
     }    
}    
 

В принципе, существует ряд операторов if / else, которые проверяют, применяются ли определенные условия, и выполняют соответствующую логику.
Последовательность if / elses сверху вниз является наиболее специфичным критерием для наиболее общих, которые применяются
, и если правило не применяется, ничего не делайте.
Это работает, но порядок зависит от if / else, и всякий раз, когда я хочу добавить новое правило, я добавляю новое if / else в «правильное» место.
Так что это не идеальное решение. Мне интересно, каков был бы наилучший способ реструктурировать мой код для этого?

Комментарии:

1. Это может быть лучше подходит для программистов

2. ооп? очевидный выбор — хранить правила как объекты.

3. martinfowler.com/bliki/RulesEngine.html

Ответ №1:

Вы не указываете какой-либо язык, поэтому мой ответ будет в основном связан с C / Java, но я думаю, что любой другой язык ооп должен предоставлять те же функции. Вы должны инкапсулировать свой критерий внутри объекта. Что-то вроде:

 enum Priority {
  HIGHEST = 0,
  HIGHER = 1,
  ...
  LOWEST = 9
}

class Criterion {
  public final Priority priority;

  public abstract boolean evaluate(YourObject object);

  Criterion(Priority priority) { this.priority = priority; }
}

class SearchCriteria {
  List<Criterion>[] criteria = new ArrayList<Criterion>[10];

  void addCriterion(Criterion criterion) {
    criteria[criterion.priority].add(criterion;
  }

  boolean evaluate(YourObject object) {
    for (List<Criterion> list : criteria)
      for (Criterion c : list)
        if (c.evaluate(object))
          return true;

    return false;
  }
}

class CountryCriterion extends Criterion {
  public final Country country;
  CountryCriterion(Country country) { super(Priority.HIGHER); this.country = country; }

  boolean evaluate(YourObject object) { return object.country.equals(country); }
}
 

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

Комментарии:

1. 1 Я думал о чем-то подобном, но был слишком ленив, чтобы записать это. Может сделать Criterion сравнение Priority и поместить их в упорядоченный список или очередь приоритетов.