开关盒D中的替代品

时间:2013-11-02 18:47:45

标签: d command-pattern

我有以下问题。

在输入consol中我可以输入一个字符串,系统会 基于此采取行动。

因此,如果我输入add_2_with_2,如果我输入,它将给我一个4 sqrt_4它会给我2等等。一般来说,你会用一个 switch / case命令,但问题是,那我需要一个 每个案件的条件。所以,如果我想ADITTIONALLY输入 cube_2,然后我必须为此写一个案例。

但是,我想在不必明确的情况下做同样的事情 每次插入新命令时写一个案例。例如,如果 在输入“FUNCTION_1”中,程序应该查看特定的 在特定的forlder /文件中,找出函数是否正确 定义并执行它。如果未在文件/文件夹中定义, 然后它应该抛出一个例外。如果我还想 输入“FUNCTION_2”,然后我将定义相同的功能 文件或文件夹(D可能的任何可能)然后让 原始程序自动搜索和执行。

这可以在D?

完成

(对不起愚蠢的问题和糟糕的英语)

3 个答案:

答案 0 :(得分:3)

碰巧,我刚做了类似的事情:

https://github.com/schancel/gameserver/blob/master/source/client/messaging.d

代码不是最漂亮的,但它使用反射来插入额外的case语句。

答案 1 :(得分:3)

是的,你可以,有几种方法可以做到。

1)您可以从一个程序内部调用函数,并使用编译时反射自动查找/映射它们。

我在终端模拟器的实用程序中这样做了。查看源代码,了解我是如何做到的: https://github.com/adamdruppe/terminal-emulator/blob/master/utility.d

要将它用于您自己的目的,您可以删除version()语句,更改模块名称并编写自己的函数。

2)您还可以在目录中查找脚本并以这种方式运行它们。使用std.process和std.file查找文件并运行它。

答案 2 :(得分:3)

我认为您正在寻找的内容通常在文献中称为 Command Pattern 。在大量OO语言中,这种模式通常涉及创建一堆类,这些类实现了一个简单的 Command 接口,该接口具有单个execute()方法。 然而,在D中,你有代表,并且可以避免为此目的生成可能有数百个小类。

这是可能的D替代方案之一,使用lambda表达式(http://dlang.org/expression.html#Lambda):

module command2;

import std.stdio;
import std.conv;
import std.array;

// 2 = binary operation
alias int delegate(int arg1, int arg2) Command2; 

// Global AA to hold all commands
Command2[string] commands;

// WARNING: assumes perfect string as input!!
void execute(string arg) {
    auto pieces = split(arg);
    int first = to!int(pieces[1]);
    int second = to!int(pieces[2]);
    Command2 cmd = commands[pieces[0]];

    int result = cmd(first, second); // notice we do not need a big switch here
    writeln(arg, " --> ", result);
} // execute() function

void main(string[] args) {
    commands["add"] = (int a, int b) => a + b;
    commands["sub"] = (int a, int b) => a - b;
    commands["sqrt"] = (int a, int b) => a * a; // second parameter ignored
    // ... add more commands (or better call them operations) here...

    execute("add 2 2");
    execute("sqrt 4 0"); // had to have 0 here because execute assumes perfect imput
} // main() function

以下是分叉和播放的源代码:http://dpaste.dzfl.pl/41d72036

当我找到更多时间时,我会写OO版本......

关于在某个目录中执行脚本/应用程序......仅仅是编写一个带参数的函数,并调用std.process.execute()。如何扩展上面代码的一个非常快速的例子:

// WARNING: no error checking, etc!
int factoriel(int arg, int ignored) {
    auto p = std.process.execute(["./funcs/factoriel", to!string(arg)]);
    return to!int(p.output);
} // factoriel() function

...
// in main()
commands["fact"] = toDelegate(&factoriel);
...
execute("fact 6 0"); // again, we add 0 because we do not know how to do unary operations, yet. :)