2015-05-29 2 views
2

У меня есть метод create(Environment env) в Java 8, который имеет несколько операторов. Теперь мне нужно переписать метод, чтобы добавить поддержку новой функции migration.Условное выполнение лямбды в Java 8

добавить поддержку migration просто означает:

Если Environment env объекта имеет поле migration набора для true не выполнить некоторый код в create функции.

Вот почему я обернуть эти блоки кода:

protected Environment create(Environment env) 
{ 
    statements; 
    if (!env.isForMigrate()) { 
     // executed only if it's NOT a migration 
     statements; 
     // for example: imh.create(ve) 
     // or: newEnv.setAps(env.getAps()); 
    } 
    ... 
    statements; 
    if (!env.isForMigrate()) { 
     // executed only if it's NOT a migration 
     statements; 
    } 
    ... 
    and so on... 
} 

Эти блоки кода я широко распространены по всей create функции. Таким образом, я должен добавить условное выполнение для нескольких блоков кода.

Могу ли я получить некоторые преимущества в случае использования лямбда-выражений для этого? Есть ли какой-либо шаблон в Java 8?

Мое намерение состоит в том, чтобы написать что-то вроде этого:

final Predicate<T> forMigrate = (func) -> { 
    // closure for Environment env 
    if (env.isForMigrate()) { 
     func(); // execute passed statements 
    } 
} 

... 
forMigrate({ 
    Environment newEnv = apsh().envh().im2aps(ve); 
    newEnv.setAps(env.getAps()); 
    newEnv.setOsId(env.getOsId()); 
}); 

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

  1. Как я могу это написать forMigrate лямбда-функция?
  2. Есть ли какие-либо преимущества использования лямбда-выражений против старых if (...) {} операторов в этом примере?

Примечание:

  1. Я не контролирую Environment класс, это автоматически генерируется из файла XML.
  2. Я хочу максимально ограничить область действия forMigration - только внутри create (не делайте его видимым в любом месте) - вот почему я хочу назначить лямбда-выражение переменной: final ... forMigrate = (...) -> { ... }.
  3. Я хочу использовать лексическую область для Environment, не передавайте ее непосредственно на лямбда. Используйте его, где определяется лямбда.

Оригинальная функция create:

protected Environment create(Environment env) 
    { 
     if(env.getHostname()!=null && env.getHostname().endsWith(".")){ 
      String normalizedHostname = env.getHostname().substring(0, env.getHostname().length() - 1); 
      env.setHostname(normalizedHostname); 
     } 
     Ve ve = apsh().envh().aps2im(env); 
     if (ve.getHostname() == null) { 
      ve.setHostname(ve.getName()); 
     } 
     List<String> apps = env.getApps(); 
     Boolean passwordSet = false; 
     imh.create(ve); 
     ve = imh.getVe(ve.getCustomerId().intValue(), ve.getName()); 
     if(env.getPassword()!= null && !env.getPassword().isEmpty()){ 
      try{ 
       imh.setVePassword(ve.getCustomerId(), ve.getName(), env.getPassword()); 
       passwordSet = true; 
      } catch(Exception ex){ 
       logger.error("Failed to set password for VE: " + env.getName(), ex); 
      } 
     } 
     if (!apps.isEmpty()) { 
      try { 
       imh.setVeApps(ve.getCustomerId().intValue(), ve.getName(), apps); 
      } catch (Exception ex) { 
       logger.error("Failed to install applications VE: {}", ex); 
      } 
     } 
     VeFacade vef = vehFactory.create(ve.getCustomerId(), ve.getName()); 
     vef.operation("start"); 

     ve = imh.getVe(ve.getCustomerId().intValue(), ve.getName()); 
     Environment newEnv = apsh().envh().im2aps(ve); 
     newEnv.setAps(env.getAps()); 
     newEnv.setOsId(env.getOsId()); 
     newEnv.setSample(env.getSample()); 
     newEnv.setHosting(env.getHosting()); 
     newEnv.setDomain(env.getDomain()); 
     newEnv.getStatus().setUptime(Long.valueOf(new Date().getTime())); 
     newEnv.setPassword(null); //prevent password from being saved in DB  
     newEnv.setPasswordSet(passwordSet); 
     apsh().envh().fillOsData(newEnv, apsh().teh().getOs(newEnv.getOsId())); 
     apsh().envh().synchPublicAddresses(newEnv, ve); 
     apsh().dnsh().synchDomainRecords(newEnv); 
     logger.info("Environment '{}' successfully created", newEnv.getName()); 
     return newEnv; 
    } 

Как бы переписать его в старом Java 7 стиле:

protected Environment create(Environment env) 
    { 
     if(env.getHostname()!=null && env.getHostname().endsWith(".")){ 
      String normalizedHostname = env.getHostname().substring(0, env.getHostname().length() - 1); 
      env.setHostname(normalizedHostname); 
     } 
     Ve ve = apsh().envh().aps2im(env); 
     if (ve.getHostname() == null) { 
      ve.setHostname(ve.getName()); 
     } 
     List<String> apps = env.getApps(); 
     Boolean passwordSet = false; 

     // NOTE: Wrap block of code 
     if (env.isForMigrate() == false) { 
      imh.create(ve); 
     } 
     ve = imh.getVe(ve.getCustomerId().intValue(), ve.getName()); 
     if(env.getPassword()!= null && !env.getPassword().isEmpty()){ 
      try{ 
       imh.setVePassword(ve.getCustomerId(), ve.getName(), env.getPassword()); 
       passwordSet = true; 
      } catch(Exception ex){ 
       logger.error("Failed to set password for VE: " + env.getName(), ex); 
      } 
     } 
     if (!apps.isEmpty()) { 
      try { 
       imh.setVeApps(ve.getCustomerId().intValue(), ve.getName(), apps); 
      } catch (Exception ex) { 
       logger.error("Failed to install applications VE: {}", ex); 
      } 
     } 

     // NOTE: Wrap block of code 
     if (env.isForMigrate() == false) { 
      VeFacade vef = vehFactory.create(ve.getCustomerId(), ve.getName()); 
      vef.operation("start"); 
     } 

     ve = imh.getVe(ve.getCustomerId().intValue(), ve.getName()); 
     Environment newEnv = apsh().envh().im2aps(ve); 
     // NOTE: Wrap block of code 
     if (env.isForMigrate() == false) { 
      newEnv.setAps(env.getAps()); 
      newEnv.setOsId(env.getOsId()); 
      newEnv.setSample(env.getSample()); 
     } 
     newEnv.setHosting(env.getHosting()); 
     newEnv.setDomain(env.getDomain()); 
     newEnv.getStatus().setUptime(Long.valueOf(new Date().getTime())); 
     newEnv.setPassword(null); //prevent password from being saved in DB  
     newEnv.setPasswordSet(passwordSet); 
     apsh().envh().fillOsData(newEnv, apsh().teh().getOs(newEnv.getOsId())); 
     apsh().envh().synchPublicAddresses(newEnv, ve); 
     apsh().dnsh().synchDomainRecords(newEnv); 
     logger.info("Environment '{}' successfully created", newEnv.getName()); 
     return newEnv; 
    } 
+3

Ваш вопрос не совсем понятен - можете ли вы показать пример с фактическим кодом, который компилирует (с или без лямбда)? – assylias

+0

Я добавил более подробную информацию, оригинальный код функции и модифицированный код (как это будет выглядеть в Java 7). – likern

ответ

2

Вы могли бы написать что-то вроде:

private static void forMigrate(Environnement env, Runnable r) { 
    if (!env.isForMigrate()) r.run(); 
} 

И в ваш код:

forMigrate(env,() -> { 
    newEnv.setAps(env.getAps()); 
    newEnv.setOsId(env.getOsId()); 
    newEnv.setSample(env.getSample()); 
    } 
); 
3

это образец на основе кода

private static class Environment { 
    private String aps; 
    private String osId; 
    private String sample; 
    private boolean forMigrate; 

    public String getAps() { 
     return aps; 
    } 
    public void setAps(String aps) { 
     this.aps = aps; 
    } 
    public String getOsId() { 
     return osId; 
    } 
    public void setOsId(String osId) { 
     this.osId = osId; 
    } 
    public String getSample() { 
     return sample; 
    } 
    public void setSample(String sample) { 
     this.sample = sample; 
    } 

    private void forMigration(Environment e, Consumer<Environment> con) { 
     if (!e.isForMigrate()) { 
      con.accept(e); 
     } 
    } 

    public boolean isForMigrate() { 
     return forMigrate; 
    } 
    public void setForMigrate(boolean isForMigrate) { 
     this.forMigrate = isForMigrate; 
    } 

    protected Environment create(Environment env) { 
     Environment newEnv= new Environment(); 
     List<String> imh=new ArrayList<>(); 
     forMigration(env, e -> {newEnv.setAps(e.getAps());newEnv.setOsId(e.getOsId()); }); 
     forMigration(env, e -> {imh.add("test for generic call"); }); 
     return newEnv; 
    } 
} 

Использование Потребителя вы можете ссылаться на один и тот же Enviroment вы используете для проверки в лямбда (если нужен был Enviroment).

+0

Спасибо! Это очень похоже на мое намерение. Но как я могу писать forMigration не как метод среды, а как выражение лямбда внутри функции create (или даже закрытие с захватом среды env)? Я добавил примечания, чтобы объяснить свои трудности. – likern

+0

@likern с моим знанием лямбда. Я не понимаю, что это возможно, или, если возможно, мой подозреваемый заключается в том, что было бы сложнее, чтобы решение java7 – Giovanni

0

Я не знаю, если это вариант для вас, но в create вы могли бы написать:

Consumer<Runnable> forMigration = runnable -> { 
    if (environment.isForMigrate()) runnable.run(); 
}; 

, а затем вызвать его так:

forMigration.accept(() -> System.out.println("migrating")); 

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

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