2015-04-04 2 views
0

Возможно ли создание и выполнение операторов Java во время выполнения.Создание операторов Java во время выполнения

себе так:

Query q = new Query("type").setFilter(filter1).setFilter(filter2).setFilter(filter3).setFilter(filterN); 

Проблема, которую я хочу, чтобы решить тот факт, что объект здесь Запрос неизменен, и я хочу, чтобы построить его на основе данного набора параметров или аргументов во время выполнения.

вшита его в методе, как:

Query query = buildQueryFromArgs(type, filterList); 

buildQueryFromArgs метод по существу создал бы заявление Java в верхней части.

Не может это сделать:

for(Filter filter : filters){ 
query = query.setFilter(filter); 
} 

потому, что будет происходить в том, что последний фильтр будет только один, который применяется. Если мы не делаем query.setFilter(f1).setFilter(f2).setFilter(andSoOn);

+0

Похоже, вы можете назвать 'setFilter' на него столько раз, сколько вы хотите; что мешает вам перебирать фильтры и делать это? –

+0

Посмотрите на рисунок Строителя –

+0

Не могли бы вы объяснить более подробно. Похоже, вы можете просто называть setFilter for-loop на каждой итерации, но вы хотите что-то еще, не так ли? – dbf

ответ

0

Похоже, что вы спрашиваете о чем-то вроде

public static Query buildQueryFromArgs(String type, List<Filter> filterList){ 
    Query resultQuery = new Query(type); 
    for (Filter f : filterList){ 
     resultQuery = resultQuery.setFilter(f); 
    } 
    return resultQuery; 
} 
+0

OP сказал, что Query неизменен, поэтому я предполагаю, что на самом деле он не имеет метода setFilter(). – Eran

+0

@Eran Будучи неизменным, это не означает, что он не может создать новый запрос с измененным состоянием. Та же идея показана в 'String', где, несмотря на неизменяемость, мы имеем метод' replace'. Но вы можете быть правы, поскольку этот вопрос не объясняется явно. – Pshemo

+0

@Pshemo благодарит за код, я обновил свой вопрос для дела – xybrek

1

Почему бы не использовать Builder?

Что-то вроде этого:

QueryBuidler qb = new QueryBuilder(type); 
for (Filter f : filterList) 
    qb = qb.setFilter(f); 
Query query = qb.build(); 

Конечно, сборка() метод, вероятно, просто вызвать конструктор запроса, который принимает тип и список (или массив) фильтров, поэтому, возможно, вы можете просто вызовите этот конструктор в первую очередь и пропустите класс QueryBuilder.

1

У вас есть два варианта:

Решение # 1 Создать метод, как вы сказали. Это будет считаться статическим заводским методом . Хотя он похож на конструктор, он позволяет указать идентификатор (имя). Хотя, если имя не является проблемой, статические заводские методы могут быть чрезмерно сложными; вы можете просто передать список и ввести его в конструктор. Ниже приведен пример статического заводского метода; используя конструктор потребует конструктор быть не частный:

class Query { 
    private List<Filter> filters; 
    private String type; 

    private Query(String type, List<Filter> filters) { 

    } 

    public static Query buildWithFilters(String type, List<Filter> filters) { 
     return new Query(type, filters); 
    } 
} 

Вы бы тогда назвать это нравится:

List<Filter> filters = new ArrayList<>(); 
//add filters 

Query query = Query.buildWithFilters("type", filters); 

Решение # 2 Builder pattern позволяет установить факультативным и обязательным состояние объекта перед его созданием. После строительства объект может оставаться неизменным.

class Query { 
    private final String type; 
    private final List<Filter> filters; 

    private Query(Builder b) { 
     type = b.type; 
     type = b.filters; 
    } 

    private static final class Builder { 
     private String type; 
     private List<Filter> filters; 

     public Builder(String type) { 
      this.type = type; 
     } 

     public Builder addFilter(Filter filter) { 
      if(filters == null) 
       filters = new ArrayList<>(); 

      filters.add(filter); 
     } 

     public Query build() { 
      return new Query(this); 
     } 
    } 
} 

Вы можете построить свой объект, как это:

Query query = new Query.Builder("type").addFilter(filter1).build(); 

Хитрость здесь хранит состояние в Builder случае перед передачей его к экземпляру, который вы пытаетесь создать.Это позволяет вам сначала указать свойства перед созданием объекта, а затем построить объект с этими свойствами через метод builder'a build().


Если вы не можете изменить Query класса, ваш следующий вариант будет создание непреложной обертки:

final class QueryWrapper { 
    private final Query query; 
    private final List<Filter> filters; 

    private QueryWrapper(Builder b) { 
     query = b.query; 
     filters = b.filters; 
    } 

    public static final class Builder { 
     private Query query; 
     private List<Filter> filters; 

     public Builder(Query query) { 
      this.query = query; 
     } 

     public Builder addFilter(Filter filter) { 
      if(filters == null) 
       filters = new ArrayList<>(); 

      filters.add(filter); 
     } 

     public QueryWrapper build() { 
      new QueryWrapper(this); 
     } 
    } 
} 

Оболочка позволяет инкапсулировать экземпляр Query. Затем клиенты связывают с оберткой Query; оболочка управляет изменчивостью.

Строитель позволяет по желанию добавлять фильтры, если хотите. Обертка неизменна, поэтому мы хотим указать дополнительные фильтры перед созданием обертки. Конструктор строителя заставляет клиента проходить в экземпляре Query (каждая обертка должна иметь Query).

+0

Невозможно изменить объект Query, потому что его библиотека из GAE (Google) – xybrek

+0

@xybrek. Вы можете создать оболочку, которая инкапсулирует 'Query'. Обновление ответа сейчас, сообщит вам –

+0

@xybrek отредактировал мой ответ. проверить это –

Смежные вопросы