基于字符串的对象创建

假设我正在编写一个聊天机器人(不和谐、电报等)。机器人可以处理聊天命令(例如 !join 告诉它加入服务器上的语音频道)。


所以在我的代码中的某个地方我必须解析命令,我会有类似的东西


String userMessage = getTheMessageTextSomehow();

// Do something with the  message.

我想为我的每个命令都有一个 Command 类,并且每个命令都会实现一个 execute() 方法。


我的问题是:创建这些命令对象的最佳实践是什么?


最简单的方法是在某个地方拥有一个大型 CommandFactory 或任何类,就像


if(message.equals(JOIN_MESSAGE) {

    return new JoinCommand();

if(message.equals(LEAVE_MESSAGE){

    return new LeaveCommand();

}

//etc...

对我来说,这看起来像是一种不好的做法和代码味道。有更好的方法吗?


慕侠2389804
浏览 82回答 3
3回答

米琪卡哇伊

您可能希望依赖 a Mapof Commands。我会明确指出,对于这个用例,使用FunctionorSupplier或任何标准功能接口根本不是惯用的。躲开它。我们可以从构建一个Command接口开始interface Command {&nbsp; &nbsp;Result execute();&nbsp;}或者如果你需要接受一个论点interface Command {&nbsp; &nbsp;Result execute(final Input input);&nbsp;}哪个将具有所需的实现class JoinCommand implements Command { ... }class LeaveCommand implements Command { ... }class NoopCommand implements Command { ... }等等。您现在需要将这些定义存储在key(命令)- value(实现)数据结构中。AMap是完美的。由于您的命令定义将是 a String,那么static final Map<String, Command> COMMANDS = new HashMap<>(8);static {&nbsp; &nbsp;COMMANDS.put("join", new JoinCommand());&nbsp; &nbsp;COMMANDS.put("leave", new LeaveCommand());&nbsp; &nbsp;// And so on}用法很简单final String userMessage = getTheMessageTextSomehow();final String commandStr = extractCommand(userMessage);final Command command = COMMANDS.getOrDefault(commandStr, NOOP_COMMAND);command.execute();或者如果你必须接受一个论点command.execute(yourInput);您还会注意到我使用NOOP_COMMAND了 ,这只是一个无操作实现,Command 以避免处理null. 它可能合适,也可能不合适。如果你在Java 9+,Map也可以使用Map.of(&nbsp; &nbsp;"join", new JoinCommand(),&nbsp;&nbsp; &nbsp;"leave", new LeaveCommand(),&nbsp; &nbsp;// And so on.)

郎朗坤

通常,它是通过映射实现的。用 simple 实现这一点会更加清晰易读Map。例如:Map<String, Command> strategies = new HashMap<String, Command>(){{&nbsp; put(JOIN_MESSAGE, new JoinCommand());&nbsp; put(LEAVE_MESSAGE, new LeaveCommand());}};及其用法:Command command = strategies.get(messageType);此外,如果您需要根据某些参数构造命令,则可以从 Java 8 开始定义创建策略(工厂)。Map<String, Function<String, Command>> strategies = new HashMap<String, Command>(){{&nbsp; put(JOIN_MESSAGE,&nbsp; param -> new JoinCommand(param));&nbsp; &nbsp;// or JoinCommand::new&nbsp; put(LEAVE_MESSAGE, param -> new LeaveCommand(param));&nbsp; // or LeaveCommand::new}};及其用法:Command command = strategies.get(messageType);command.process(param);

大话西游666

您好,您尝试使用 Switch Case 语句,它很容易理解,并且将来如果您有任何更改,那么很容易更新代码。switch(message)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;case JOIN_MESSAGE:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new JoinCommand();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp;case LEAVE_MESSAGE:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new LeaveCommand();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java