У меня есть метод 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
.
- Как я могу это написать
forMigrate
лямбда-функция? - Есть ли какие-либо преимущества использования лямбда-выражений против старых
if (...) {}
операторов в этом примере?
Примечание:
- Я не контролирую
Environment
класс, это автоматически генерируется из файла XML. - Я хочу максимально ограничить область действия
forMigration
- только внутриcreate
(не делайте его видимым в любом месте) - вот почему я хочу назначить лямбда-выражение переменной:final ... forMigrate = (...) -> { ... }
. - Я хочу использовать лексическую область для
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;
}
Ваш вопрос не совсем понятен - можете ли вы показать пример с фактическим кодом, который компилирует (с или без лямбда)? – assylias
Я добавил более подробную информацию, оригинальный код функции и модифицированный код (как это будет выглядеть в Java 7). – likern