自执行命令

时间:2017-01-05 13:43:08

标签: java design-patterns dsl

这段代码是命令和构建器模式的混合:

    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中是否可行?

编辑附加信息

也许我的错误在于我没有提供有关意图的任何信息。我试图模糊这个问题,不要让它难以理解,也不能过于宽泛地回答。

所以这段代码就是DSL。这是命令只执行操作的最简单情况(例如,在数据库中存储一些信息)。另一种情况是命令必须返回一个值(使用build()方法完全实现Builder模式) - 但在这种情况下,如果总是在链中的最后一个方法,则没有问题导致返回。

我认为真正的问题是: 如何延迟评估直到整个构建器方法链被处理?

2 个答案:

答案 0 :(得分:1)

你可以用lambda得到你想要的东西:

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));

答案 1 :(得分: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中没有其他解决方案,因为不得不以某种方式调用执行方法。