Java 带有附加参数解析的命令模式

Java 带有附加参数解析的命令模式,java,parsing,design-patterns,structure,Java,Parsing,Design Patterns,Structure,最近,我非常关注设计模式,并实现它们来解决不同的问题。今天我正在研究命令模式 我最终创建了一个界面: public interface Command { public void execute(); } 我有几个具体的实现: public class PullCommand implements Command { public void execute() { // logic } } 以及: 还有其他几个命令 现在。。问题是有一个Blockin

最近,我非常关注设计模式,并实现它们来解决不同的问题。今天我正在研究命令模式

我最终创建了一个界面:

public interface Command {
    public void execute();
}
我有几个具体的实现:

public class PullCommand implements Command {

    public void execute() {
        // logic
    }
}
以及:

还有其他几个命令

现在。。问题是有一个BlockingQueue运行在另一个线程上,它使用.take来检索排队的命令,并在它们进入时执行它们。我将通过另一个类调用下面的Executor类,该类通过解析用户输入并使用.queue生成这些命令。到目前为止还不错

我最困难的部分是解析命令CLI应用程序。 我已将它们全部放在HashMap中:

private HashMap<String, Command> commands = new HashMap<String, Command>();
commands.put("pull", new PullCommand());
commands.put("push", new PushCommand());
//etc..
根据传递给工厂的字符串,其process方法将对该命令使用适当的解析,并返回相应的command对象,但这意味着该类可能非常大,因为它包含对所有命令的解析


总的来说,这似乎是我唯一的选择,但我非常犹豫,因为从结构的角度来看,我认为我没有很好地解决这个问题。这是处理这种情况的好方法吗?我有什么遗漏吗?有没有办法重构我的部分代码来简化它?

你想得太多了。命令模式基本上是保留您需要知道如何做某事的所有内容,然后再做,因此可以将这些内容传递给执行代码

只要这样做:

用户输入字符串[] 第一个字符串是命令名,请按现在的方式使用它 其余字符串是命令的参数(如果有) 将您的接口更改为public void executeString[]参数; 要执行,请将参数传递给命令对象
一般来说,像这样广泛地提出一个设计问题并不是一个好主意。这是有点令人惊讶,只看到一个向下的投票,而没有密切的要求

在任何情况下,如果不彻底了解您的问题,就很难说什么是最好的设计,更不用说如果我这样做了,我不会说任何东西是最好的。因此,我将使用Builder模式坚持我所说的

一般来说,只要构造逻辑过于复杂而无法装入构造函数,或者必须将其划分为多个阶段,就会使用构建器模式。在这种情况下,如果您希望根据操作的不同,使命令的外观具有极大的多样性,那么您将需要以下生成器:

interface CommandBuilder<T extends Command> {
    void parseArgs(String[] args);
    T build();
}
HashMap<String, Supplier<? extends CommandBuilder<? extends Command>>> builders = new HashMap<>();
commands.put("pull", () -> new PullBuilder());
commands.put("push", () -> new PushBuilder());
// etc
正如您所希望的,这些构建器中的任何一个都可能具有极其复杂的逻辑。那你就可以了

CommandBuilder builder = builders.get(args[0]).get();
builder.setArgs(args);
queue.add(builder.build());
通过这种方式,您的命令界面可以专注于它应该做什么

请注意,在构建构建器映射之后,一切都是静态的,并且突变是局部的。我不完全理解你的担忧,但应该通过这样做来解决


但是,这可能是一个过于夸张的设计,取决于你想做什么。对不起,太长了,所以我在中间停了下来。让我总结一下,您的问题基本上是,您是否可以将命令行解析的逻辑与命令接口分离,是吗?那么,您可以使用生成器模式,不是吗?您在最后提到了factory,但从技术上讲,它应该是生成器模式。检查命令是否无效时,只需执行commands.containsKeyarguments[0],如果为真,则应执行该命令。使用内置的hashmap方法。如果地图不包含该键,则没有理由调用get。这就是为什么在第一部分中存在containsKey方法的原因place@HuStmpHrrr是的,sumarized可以这么说。。我正在寻找这种情况下最好的结构性解决方案。我还没有想到建设者的模式,我感到非常惊讶,我怎么会错过这一点。这听起来是个不错的选择。@RAZ_Muh_Taz我对此没有任何问题,所以这毫无帮助,我在这里谈论的是更大范围的结构解决方案。我对HashMap没有问题。@hustmphrr在实现构建器模式时,我必须对每个命令执行它-PullCommand、PushCommand等。。但是HashMap包含一个命令界面,当从HashMap检索时,构建器将不可见。试图在接口内部实现构建器模式来解决这一问题似乎是错误的。因此,我还必须改变将命令排入Executor类的方式,该类包含BlockingQueue,并调用execute,但不包含参数,我必须稍微重构它。@Hubbs不完全如此。创建一个包含命令字段和字符串[]的包装类,然后对这些字段进行排队。在执行时,将字符串[]传递给命令。
HashMap<String, Supplier<? extends CommandBuilder<? extends Command>>> builders = new HashMap<>();
commands.put("pull", () -> new PullBuilder());
commands.put("push", () -> new PushBuilder());
// etc
CommandBuilder builder = builders.get(args[0]).get();
builder.setArgs(args);
queue.add(builder.build());