Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何过度设计外壳_Java_Shell_Oop_Design Patterns - Fatal编程技术网

Java 如何过度设计外壳

Java 如何过度设计外壳,java,shell,oop,design-patterns,Java,Shell,Oop,Design Patterns,昨天我遇到了一个问题,它询问如何使用创建一个OO外壳 这让我很好奇,因为我总是讨厌我的贝壳(一连串的如果和其他)。我用一个完全有效的例子来回答这个问题 这里有一个小摘录,描述了主要思想 private final Writer writer = new BufferedWriter(new OutputStreamWriter( System.out)); private boolean quit = false; private Map<Stri

昨天我遇到了一个问题,它询问如何使用创建一个OO外壳

这让我很好奇,因为我总是讨厌我的贝壳(一连串的如果和其他)。我用一个完全有效的例子来回答这个问题

这里有一个小摘录,描述了主要思想

private final Writer writer = new BufferedWriter(new OutputStreamWriter(
            System.out));
    private boolean quit = false;

    private Map<String, Command> commands = new HashMap<>();
    {
        commands.put("create", new CreateChat(this));
        commands.put("join", new JoinChat(this));
        commands.put("exit", new ExitCommand(this));
    }

    public void run() throws IOException {
        try (Scanner s = new Scanner(System.in)) {
            writer.write("> ");
            writer.flush();
            while (!quit && s.hasNextLine()) {
                String input = s.nextLine().trim();

                // get or default is java8, alternatively you could check for null
                Command command = commands.getOrDefault(input, new UnknownCommand(this, input));
                command.execute();

                if (!quit)
                    writer.write("> ");
                writer.flush();
            }
        }
    }
private final Writer Writer=new BufferedWriter(new OutputStreamWriter(
系统(out),;
private boolean quit=false;
私有映射命令=new HashMap();
{
commands.put(“create”,newcreatechat(this));
commands.put(“join”,newjoinchat(this));
commands.put(“exit”,新ExitCommand(this));
}
public void run()引发IOException{
try(扫描器s=新扫描器(System.in)){
作者:写(“>”);
writer.flush();
而(!quit&s.hasNextLine()){
字符串输入=s.nextLine().trim();
//get或default是java8,或者您可以检查null
Command Command=commands.getOrDefault(输入,新的未知命令(此,输入));
command.execute();
如果(!退出)
作者:写(“>”);
writer.flush();
}
}
}
不过,我并不完全满意。我更喜欢声明式解决方案,您可以指定命令并将它们映射到
命令
接口的适当实例

我的问题是,我不知道如何处理复杂的输入,例如

采集样本

采集样本1.0 1.5 1.33 1.45

班主任学生…

我可以将命令实例交给
Reader
对象,但我觉得读取自己的输入不是他们的责任。它们应该有一个
CommandParameter
对象等

但我不知道如何设计它。我曾经实现过一个二进制协议解析库,它使用户能够通过xml定义协议,这似乎是一个解决方案(但很复杂)

另一个问题是,如果无法创建
CommandParameter
,我如何告诉用户何时以及在何处发生格式错误


TL;DR

最后,我要提出一个明确的问题: 我们可以利用什么样的设计模式来创建一个干净的shell(以声明的方式),同时尊重所有常见的设计模式 清洁代码规则(关注点分离、单一责任原则等)


*“shell”是指(java)程序的一部分,它从
系统中读取预定义的命令,并在模型/控制器上调用相应的方法。

广义上说,设计shell时有两种思想:

  • Unix理念:“文本是通用接口”。大多数受Unix启发的工具从stdin读取文本,并将文本输出到stdout以相互交互。这种将文本作为通用接口的理念之所以产生,是因为这些工具是由大量异构作者用异构语言编写的,这些作者甚至可能从未见过或听说过彼此。一个工具可以由荷兰的某个人用C编写,另一个工具由澳大利亚的一个团队用Python编写,另一个工具是Perl脚本,它已经在不同的论坛上被无数人传递和修改,等等,它们需要彼此互操作。unixshell拥有强大的工具,可以转换文本流,将一个程序的输出提供给另一个程序(sed、grep等)。缺点是每个工具都必须实现自己的解析

  • 基于对象的shell,最著名的是PowerShell,但它也是Python、Ruby、Lisp等更传统编程语言的REPL。在这种理念中,shell中有对象,shell工具交换这些对象而不是文本。基于对象的shell通常更易于使用,前提是这些工具的作者已经将他们的工具设计为可以一起使用(如果所有工具都是由一个作者或一个统一的作者组编写的,则通常是这种情况)。缺点是,几乎所有内容都必须用一种语言或一组共享公共运行时的语言编写(例如.NET)


  • 但无论哪种情况,设计模式都很简单。在unixshell哲学中,这些工具在文件系统中声明为程序,shell只执行这些程序。另一方面,在基于对象的shell理念中,您需要动态导入类文件,并且需要使用内省,以便shell能够确定如何调用该工具。

    如果您投票关闭,请添加注释。这给了我修改/澄清问题的机会。提前谢谢<代码>缺点是每个工具都必须实现自己的解析。
    我指的正是那个解析。你如何设计它?我想我们对“壳”这个词有点误解。但是谢谢你有趣的回答@迈克:对于unixshell,解析由工具来完成,shell只有一些工具可以帮助转换文本。文本是通用的。在每个工具中,它们如何解析输入文本取决于工具,一些工具通过在Antlr、EBNF或Lex/Yacc中定义语法来完成整个过程,另一些工具只是通过数据使用regex,许多工具只是从输入流中使用令牌。它是决定如何最好地解析自己的输入的单独工具,shell不(需要)定义我们对解析的关注,它只需要设置流重定向。@mike:shell解析的唯一部分是命令行参数(argv数组)。在大多数unixshell中,这只是在空白处拆分命令行参数,并使用引号或转义字符防止拆分。然后由工具决定如何处理字符串数组。命令行完成只是作为单词列表或纸条实现的