处理控制台命令的最佳Java设计模式

处理控制台命令的最佳Java设计模式,java,design-patterns,console,Java,Design Patterns,Console,我试图创建一个控制台来处理字符串中的控制台命令 目前,我使用if语句检查每个命令,如下所示: if (command.contains("new train")) { command = command.replace("new train ", ""); Train t = new Train(); t.setCode(command); ServiceProvider.getTrainService().saveOrUpdate(t); respone

我试图创建一个控制台来处理
字符串中的控制台命令

目前,我使用if语句检查每个命令,如下所示:

if (command.contains("new train")) {
    command = command.replace("new train ", "");
    Train t = new Train();
    t.setCode(command);
    ServiceProvider.getTrainService().saveOrUpdate(t);
    responeHandler("train " + command + " created");
}
但在我看来,这不是最好的解决方案

我想知道对于这样的问题是否已经有了一个好的设计模式

我查看了
builder
factory
模式,但无法确定它们是否是正确的选择。

A
Map
可以将命令与操作关联起来。
它不是GOF工厂和命令DP。
但这些都是工厂和命令模式的公平而简单的实现。
所以你也应该考虑一下。

Map<String, Consumer<String>> actionsByCommand = new HashMap<>();

actionsByCommand.put("new train", command->{
     command = command.replace("new train ", "");
        Train t = new Train();
        t.setCode(command);
        ServiceProvider.getTrainService().saveOrUpdate(t);
        responeHandler("train " + command + " created");
});

actionsByCommand.put("delete train", command->{
     command = command.replace("delete train ", "");
     ...
});

// and so for...
以及以相同方式定义的其他操作

然后您可以这样使用它们:

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
    String command = scanner.nextLine();
    Consumer<String> action = actionsByCommand.getOrDefault(command, invalidCommandAction);
    action.accept(command);
}
Scanner Scanner=新的扫描仪(System.in);
while(scanner.hasNextLine()){
String命令=scanner.nextLine();
使用者操作=actionsByCommand.getOrDefault(命令,invalidCommandAction);
接受(命令);
}
A
Map
可以将命令与操作关联起来。
它不是GOF工厂和命令DP。
但这些都是工厂和命令模式的公平而简单的实现。
所以你也应该考虑一下。

Map<String, Consumer<String>> actionsByCommand = new HashMap<>();

actionsByCommand.put("new train", command->{
     command = command.replace("new train ", "");
        Train t = new Train();
        t.setCode(command);
        ServiceProvider.getTrainService().saveOrUpdate(t);
        responeHandler("train " + command + " created");
});

actionsByCommand.put("delete train", command->{
     command = command.replace("delete train ", "");
     ...
});

// and so for...
以及以相同方式定义的其他操作

然后您可以这样使用它们:

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
    String command = scanner.nextLine();
    Consumer<String> action = actionsByCommand.getOrDefault(command, invalidCommandAction);
    action.accept(command);
}
Scanner Scanner=新的扫描仪(System.in);
while(scanner.hasNextLine()){
String命令=scanner.nextLine();
使用者操作=actionsByCommand.getOrDefault(命令,invalidCommandAction);
接受(命令);
}

A
命令
工厂
模式是否可能

interface Command {
    void execute();
}

interface CommandFactory {
    boolean canCreate(String input);
    Command fromInput(String input); // or return Optional so it can be a FunctionalInterface
}

class TrainCommand implements Command {
    String train;
    public TrainCommand(String t) {  train = t; }
    public void execute() {
        ServiceProvider.getTrainService().saveOrUpdate(t);
    }
}

class TrainCommandFactory {
    public boolean canCreate(String t) {
        return t.contains("new train ");
    }
    public Command fromString(String c) {
        return new TrainCommand(c.replace("new train ", ""));
    }
}
以及迭代所有已知命令工厂的
单例
复合
命令工厂:

class CommandFactories implements CommandFactory {
    private static final CommandFactories INSTANCE;
    private List<CommandFactory> delegates = Arrays.asList(
        new TrainCommandFactory()
        // others
    };
    public boolean canCreate(String t) {
        return delegates.stream()
            .filter(cf -> cf.canCreate(t))
            .findAny().isPresent();
    }
    public Command fromString(String c) {
        return delegates.stream()
            .filter(cf -> cf.canCreate(t))
            .findAny()
            .map(CommandFactory::fromString);
    }
}
类CommandFactories实现CommandFactory{
私有静态最终命令实例;
私有列表委托=Arrays.asList(
新工厂()
//其他
};
公共布尔值canCreate(字符串t){
返回委托。stream()
.filter(cf->cf.canCreate(t))
.findAny().isPresent();
}
公共命令fromString(字符串c){
返回委托。stream()
.filter(cf->cf.canCreate(t))
.findAny()
.map(CommandFactory::fromString);
}
}

A
命令
工厂
模式是否可能

interface Command {
    void execute();
}

interface CommandFactory {
    boolean canCreate(String input);
    Command fromInput(String input); // or return Optional so it can be a FunctionalInterface
}

class TrainCommand implements Command {
    String train;
    public TrainCommand(String t) {  train = t; }
    public void execute() {
        ServiceProvider.getTrainService().saveOrUpdate(t);
    }
}

class TrainCommandFactory {
    public boolean canCreate(String t) {
        return t.contains("new train ");
    }
    public Command fromString(String c) {
        return new TrainCommand(c.replace("new train ", ""));
    }
}
以及迭代所有已知命令工厂的
单例
复合
命令工厂:

class CommandFactories implements CommandFactory {
    private static final CommandFactories INSTANCE;
    private List<CommandFactory> delegates = Arrays.asList(
        new TrainCommandFactory()
        // others
    };
    public boolean canCreate(String t) {
        return delegates.stream()
            .filter(cf -> cf.canCreate(t))
            .findAny().isPresent();
    }
    public Command fromString(String c) {
        return delegates.stream()
            .filter(cf -> cf.canCreate(t))
            .findAny()
            .map(CommandFactory::fromString);
    }
}
类CommandFactories实现CommandFactory{
私有静态最终命令实例;
私有列表委托=Arrays.asList(
新工厂()
//其他
};
公共布尔值canCreate(字符串t){
返回委托。stream()
.filter(cf->cf.canCreate(t))
.findAny().isPresent();
}
公共命令fromString(字符串c){
返回委托。stream()
.filter(cf->cf.canCreate(t))
.findAny()
.map(CommandFactory::fromString);
}
}

如果您身处春季世界,您可以使用

<>你可以考虑实施< /P>
org.springframework.boot.CommandLineRunner
每个命令都可以在其自己的CommandLineRunne实例中执行

使用


要解析命令行,如果您在Spring世界中,可以使用

<>你可以考虑实施< /P>
org.springframework.boot.CommandLineRunner
每个命令都可以在其自己的CommandLineRunne实例中执行

使用


要分析命令行,可以将命令存储在数组中,当用户输入命令时,可以找到具有给定索引的项。该索引在开关情况下有意义且可用,如果找不到该项,则可以给出有意义的响应

此外,可以通过不区分大小写的方式执行此操作,即让数组中的键都是小写字符,并在搜索之前将命令键转到小写:

protected String[] supportedCommands = {"first", "second", "third"};
public static int findCommand(String command) {
    for (var i = 0; i < supportedCommands.length; i++) {
        if (command.equals(supportedCommands[i])) return i;
    }
    return -1; //Not found
}

public static void handleCommand(String command) {
    int c = findCommand(command.toLowerCase());
    switch (c) {
        case 1: {/*...*/} break;
        default: {/*Handle Undefined command*/}
    }
}
protectedstring[]supportedCommands={“第一”、“第二”、“第三”};
公共静态int findCommand(String命令){
对于(var i=0;i
您可以将命令存储在数组中,当用户输入命令时,您可以找到具有给定索引的项。该索引在切换情况下有意义且可用,如果找不到该项,您可以给出有意义的响应

此外,可以通过不区分大小写的方式执行此操作,即让数组中的键都是小写字符,并在搜索之前将命令键转到小写:

protected String[] supportedCommands = {"first", "second", "third"};
public static int findCommand(String command) {
    for (var i = 0; i < supportedCommands.length; i++) {
        if (command.equals(supportedCommands[i])) return i;
    }
    return -1; //Not found
}

public static void handleCommand(String command) {
    int c = findCommand(command.toLowerCase());
    switch (c) {
        case 1: {/*...*/} break;
        default: {/*Handle Undefined command*/}
    }
}
protectedstring[]supportedCommands={“第一”、“第二”、“第三”};
公共静态int findCommand(String命令){
对于(var i=0;i
我认为使用已定义的命令是正确的方法。命令的一个重要问题是通过
命令字符串
识别(
匹配
)并执行(
执行
)。一旦创建了自定义的
命令
,就可以在列表中注册并执行它们

interface Command{
    boolean matches(String commandString);
    boolean execute(String commandString);
}
一个示例实现是

CreateTrainCommand implements Command{

    private final CMDSTRING = "new train";

    @Override
    public boolean matches(CommandString cmdStr){
        if(cmdStr != null && cmdStr.toLowerCase.startsWith(CMDSTRING)){
            return true;
        }
        return false;
    }

    @Override
    public boolean matches(CommandString cmdStr){
         if(cmdStr != null){
             String train = cmdString.toLowerCase.replace(CMDSTRING, "").trim();

             //here comes your command execution
             Train t = new Train();
             ...
         }
        return true;//execution succesful
    }
}
如果要使用这些命令,请将所有命令存储到列表(或任何其他集合)中,并检查命令是否与输入匹配

List<Command> cmds = ...
cmds.add(new CreateTrainCommand()); //add all commands that were implemented 
//or only some commands if the user has restricted access

我认为使用已定义的命令是正确的方法