【发布时间】:2016-12-16 12:03:00
【问题描述】:
下面是命令模式,其中你有一个命令和一个命令处理程序,它们被添加到CommandBus,然后在被调用时在那里执行。在这种情况下,该命令有一个类型 <string>,我希望在执行 CommandBus 中的命令时返回它
问题是最后一行var whatIsThis = CommandBus.execute<string>(new GetStringCommand("Hello, world"));,更具体地说,我想从该语句中删除,因为它应该来自Command。 CommandBus 类应该知道它应该从 class GetStringCommand implements Command<string> 返回。
interface Command<T> {
name:string;
}
class GetStringCommand implements Command<string> {
public str:string;
public name:string = "GetStringCommand";
constructor(str:string){
this.str = str;
}
}
interface CommandHandler<T> {
execute(command:Command<T>): T;
}
class GetStringHandler implements CommandHandler<string> {
execute(command:GetStringCommand):string {
return command.str;
}
}
interface CommandRegistry {
[x:string]: CommandHandler<any>
}
class CommandBus {
private static actions:CommandRegistry = {};
static add(name:string, command:CommandHandler<any>) {
CommandBus.actions[name] = command;
}
static execute<T>(command:Command<T>) : T {
return CommandBus.actions[command.name].execute(command);
}
}
CommandBus.add("GetStringCommand", new GetStringHandler());
var whatIsThis = CommandBus.execute<string>(new 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);
}
}
【问题讨论】:
-
为什么需要处理程序?你不能只在
Command中有execute吗? -
关注点分离。这个想法是一个命令可以被多个命令处理程序使用,例如,对于一个保存操作,并且您有多个数据库系统,然后这些数据库将每个都有一个命令处理程序来执行该操作(并且它们本质上将成为即插即用play),你不需要为所有数据库编写一个巨大的命令,而且,如果你想自定义你想要使用的数据库,那么......如果没有处理程序,这将是不可能的
-
如果您有不同的数据库,那么您需要不同的命令才能使用它们。除非我在您的设计中遗漏了某些东西,否则处理程序似乎只是返回值的命令的包装器。也许你可以在你的代码中加入一个更有趣的例子?
-
见上面的例子
标签: typescript command-pattern