2017-01-05 6 views
1

Этот фрагмент кода представляет собой смесь шаблонов команд и строителя:Самого выполнения команда

CommandBuilder.create("one value").execute(); 

    CommandBuilder.create("another value").withBigDecimal(BigDecimal.ZERO).withNumber(123).execute(); 

все это делает простую печать:

one value 
another value 123 0 

Цель состоит в том, чтобы избавиться от execute() метод. Это означает, что после последнего метода withXXX() (или без какого-либо withXXX()) код выполнил бы печать.

Вот текущий код:

import java.math.BigDecimal; 

public class CommandBuilder { 

    private final String value; 
    private Integer number; 
    private BigDecimal bigDecimal; 

    private CommandBuilder(String value) { 
     this.value = value; 
    } 

    public static CommandBuilder create(String value){ 
     return new CommandBuilder(value); 
    } 

    public CommandBuilder withNumber(Integer number){ 
     this.number = number; 
     return this; 
    } 

    public CommandBuilder withBigDecimal(BigDecimal bigDecimal){ 
     this.bigDecimal = bigDecimal; 
     return this; 
    } 

    public void execute(){ 
     StringBuilder sb = new StringBuilder(); 
     sb.append(value); 
     if(number != null){ 
      sb.append(" ").append(number); 
     } 
     if(bigDecimal != null){ 
      sb.append(" ").append(bigDecimal); 
     } 

     System.out.println(sb); 
    } 
} 

Возможно ли это в Java?

EDIT ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

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

Таким образом, этот фрагмент кода является DSL. Это самый простой случай, когда команды просто выполняют действие (например, хранят некоторую информацию в базе данных). Другой случай - когда команда должна вернуть значение (полная реализация шаблона Builder с помощью метода build()), но в этом случае нет проблемы, вызывающей возврат, если всегда последний метод в цепочке.

Я думаю, что настоящая проблема: Как отложить оценку до тех пор, пока вся цепочка методов построения не обработана?

ответ

0

Вы можете сделать что-л. Следующим образом: import java.math.BigDecimal;

public class CommandBuilder { 

    private final String value; 
    private Integer number; 
    private BigDecimal bigDecimal; 

    private CommandBuilder(String value) { 
     this.value = value; 
    } 

    public static CommandBuilder create(String value){ 
     return new CommandBuilder(value); 
    } 

    public static CommandBuilder create(String value, boolean exec){ 
     CommandBuilder builder = create(value); 
     if(exec){ 
      execute(); 
     } 
     return builder; 

    } 


    public CommandBuilder withNumber(Integer number){ 
     this.number = number; 
     return this; 
    } 

    public CommandBuilder withNumber(Integer number, boolean exec){ 
     CommandBuilder builder = withNumber(number); 
     if(exec){ 
      execute(); 
     } 
     return builder; 
    } 

    public CommandBuilder withBigDecimal(BigDecimal bigDecimal){ 
     this.bigDecimal = bigDecimal; 
     return this; 
    } 

    public CommandBuilder withBigDecimal(BigDecimal bigDecimal, boolean exec){ 
     CommandBuilder builder = withBigDecimal(bigDecimal); 
     if(exec){ 
      execute(); 
     } 
     return builder; 
    } 

    public void execute(){ 
     StringBuilder sb = new StringBuilder(); 
     sb.append(value); 
     if(number != null){ 
      sb.append(" ").append(number); 
     } 
     if(bigDecimal != null){ 
      sb.append(" ").append(bigDecimal); 
     } 

     System.out.println(sb); 
    } 
} 

И затем использовать его как следующее:

CommandBuilder.create("anothervalue").withBigDecimal(BigDecimal.ZERO).withNumber(123, true); 

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

1

Вы можете получить то, что вы хотите с лямбда:

import java.math.BigDecimal; 
import java.util.function.Consumer; 

class CommandBuilder { 

    private final String value; 
    private Integer number; 
    private BigDecimal bigDecimal; 

    private CommandBuilder(String value) { 
     this.value = value; 
    } 

    public static void createAndExecute(String value, Consumer<CommandBuilder> consumer){ 
     CommandBuilder builder = new CommandBuilder(value); 
     consumer.accept(builder); 
     builder.execute(); 
    } 

    public CommandBuilder withNumber(Integer number){ 
     this.number = number; 
     return this; 
    } 

public CommandBuilder withBigDecimal(BigDecimal bigDecimal){ 
    this.bigDecimal = bigDecimal; 
    return this; 
} 

public void execute(){ 
    StringBuilder sb = new StringBuilder(); 
    sb.append(value); 
    if(number != null){ 
     sb.append(" ").append(number); 
    } 
    if(bigDecimal != null){ 
     sb.append(" ").append(bigDecimal); 
    } 

    System.out.println(sb); 
} 

}

И использовать его как это:

CommandBuilder.createAndExecute("something", builder -> builder.withNumber(1)); 

Я думаю, было бы лучше, однако, чтобы установить значение также в таких Потребителях:

CommandBuilder.createAndExecute(builder -> builder.withValue("something").withNumber(1)); 
+0

Мне нравится ваш дизайн - это самый простой и четкий способ. Тем не менее он меняет API. Я должен сказать, что при использовании последнего подхода (где Consumer управляет всеми параметрами) у вас нет возможности принудительно вводить обязательные параметры во время компиляции. Поэтому первое использование лучше всего подходит. – pawelccb