Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.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
Typescript命令模式返回类型_Typescript_Command Pattern - Fatal编程技术网

Typescript命令模式返回类型

Typescript命令模式返回类型,typescript,command-pattern,Typescript,Command Pattern,下面是命令模式,其中有一个命令和一个命令处理程序,它们被添加到CommandBus中,然后在调用时在那里执行。在本例中,命令有一个类型,我希望在CommandBus中执行命令时返回该类型 问题是最后一行var whatisset=CommandBus.execute(新的GetStringCommand(“Hello,world”)更具体地说,我想删除该语句,因为它应该来自命令。CommandBus类应该知道它应该从类GetStringCommand implements命令返回 接口命令{ 名

下面是命令模式,其中有一个命令和一个命令处理程序,它们被添加到
CommandBus
中,然后在调用时在那里执行。在本例中,命令有一个类型
,我希望在
CommandBus
中执行命令时返回该类型

问题是最后一行
var whatisset=CommandBus.execute(新的GetStringCommand(“Hello,world”)
更具体地说,我想删除该语句,因为它应该来自
命令
CommandBus
类应该知道它应该从
类GetStringCommand implements命令返回

接口命令{
名称:字符串;
}
类GetStringCommand实现该命令{
公共str:string;
公共名称:string=“GetStringCommand”;
构造函数(str:string){
this.str=str;
}
}
接口命令处理程序{
执行(命令:命令):T;
}
类GetStringHandler实现CommandHandler{
执行(命令:GetStringCommand):字符串{
return命令.str;
}
}
接口命令注册表{
[x:string]:CommandHandler
}
类命令总线{
私有静态操作:CommandRegistry={};
静态添加(名称:字符串,命令:CommandHandler){
CommandBus.actions[name]=命令;
}
静态执行(命令:命令):T{
返回CommandBus.actions[command.name].execute(command);
}
}
add(“GetStringCommand”,新的GetStringHandler());
var whatIsThis=CommandBus.execute(新的GetStringCommand(“Hello,world”);
上面的解决方案是有效的,效果很好,但是这是一个糟糕的解决方案,因为它使重构变得痛苦,而且它让我不得不一遍又一遍地重复自己,因为我将使用数千条命令

实例 下面是一个在MongoDB中保存模式的命令处理程序示例,相同的命令可用于在MySQL中创建模式

export class SaveSchemaCommandHandler implements CommandHandlerBase<void> {
    execute(command:SaveSchemaCommand) {
        var db = MongoConnection.db;
        var collectionOptions = { autoIndexID: true };

        db.createCollection(command.schema.getName(), collectionOptions);
    }
}
导出类SaveSchemaCommandHandler实现CommandHandlerBase{
执行(命令:SaveSchemaCommand){
var db=MongoConnection.db;
var collectionOptions={autoIndexID:true};
createCollection(command.schema.getName(),collectionOptions);
}
}

据我所知,您的处理程序是真正的命令,而您所调用的命令只是处理程序执行所需的参数

您可以用简单的界面替换您的“命令”,您的处理程序将成为命令。
然后,您就可以消除这些新命令对类的需求,因为您可以将execute函数作为命令传递

大概是这样的:

interface CommandData {}

interface GetStringCommandData extends CommandData {
    value: string;
}

interface SaveSchemaCommandData extends CommandData {
    schema: { name: string };
}

type Command<In extends CommandData, Out> = (data: In) => Out;

interface CommandRegistry {
    [x: string]: Command<CommandData, any>;
}

class CommandBus {
    private static actions:CommandRegistry = {};

    static add(name: string, command: Command<CommandData, any>) {
        CommandBus.actions[name] = command;
    }

    static execute<T>(name: string, data: CommandData) : T {
        return CommandBus.actions[name](data);
    }
}

CommandBus.add("GetStringCommand", (data: GetStringCommandData) => data.value);
CommandBus.add("SaveSchemaCommand", (data: SaveSchemaCommandData) => {
    let db = MongoConnection.db;
    let collectionOptions = { autoIndexID: true };

    db.createCollection(data.schema.name, collectionOptions);
});

CommandBus.execute("GetStringCommand", { value: "my string" });
CommandBus.execute("SaveSchemaCommand", { schema: { name: "mySchema" } });
(2) 使用
any

class CommandBus {
    ...

    static execute(name: string, data: CommandData): any {
        return CommandBus.actions[name](data);
    }
}

let str: string = CommandBus.execute("GetStringCommand", { value: "my string" });
(3) 为执行声明可能的签名:

class CommandBus {
    ...

    static execute(name: "GetStringCommand", data: GetStringCommandData): string;
    static execute(name: "SaveSchemaCommand", data: SaveSchemaCommandData): void;
    static execute(name: string, data: CommandData): any;
    static execute(name: string, data: CommandData): any {
        return CommandBus.actions[name](data);
    }
}

let str: string = CommandBus.execute("GetStringCommand", { value: "my string" });

此选项不太可扩展,但它仍然是一个选项。

为什么需要处理程序?您不能在
命令
?分离关注点中执行
吗。其思想是,一个命令可以被多个命令处理程序使用,例如,对于一个保存操作,您有多个数据库系统,这些数据库将分别有一个命令处理程序来执行该操作(实际上它们将成为即插即用),您不需要为所有数据库编写一个巨大的命令,而且,如果您想自定义要使用的数据库,那么。。如果你有不同的数据库,那么你需要不同的命令来使用它们。除非我在您的设计中遗漏了什么,否则处理程序似乎只是返回值的命令的包装器。也许您可以在代码中包含一个更有趣的示例?请参见上面的示例,我认为用接口替换命令是一个好主意,因为它们只包含结构,但是上面的返回类型有一个问题:
var xyz:string=CommandBus.execute(“GetStringCommand”,{value:“my string”})
会给出错误“Type'{}'不可分配给Type'string'”,您可以在前面传入,但我想避免这种情况。我认为这个解决方案已经足够好了,函数必须是类,因为它们包含的类多于正常执行的类,谢谢您的帮助!检查我修改过的答案,我给了你3个选项来处理这个问题。@NitzanTomer在你的第一个例子中,当执行命令时,我会传入
GetStringCommandData
,而不是基本的
CommandData
。但是泛型的返回类型推断似乎丢失了,变成了
{}
。有没有一种方法可以避免在
GetStringCommandData
中包含泛型
class CommandBus {
    ...

    static execute(name: string, data: CommandData): any {
        return CommandBus.actions[name](data);
    }
}

let str: string = CommandBus.execute("GetStringCommand", { value: "my string" });
class CommandBus {
    ...

    static execute(name: "GetStringCommand", data: GetStringCommandData): string;
    static execute(name: "SaveSchemaCommand", data: SaveSchemaCommandData): void;
    static execute(name: string, data: CommandData): any;
    static execute(name: string, data: CommandData): any {
        return CommandBus.actions[name](data);
    }
}

let str: string = CommandBus.execute("GetStringCommand", { value: "my string" });