为了账号安全,请及时绑定邮箱和手机立即绑定

基于字符串的对象创建

基于字符串的对象创建

慕侠2389804 2022-07-27 09:34:58
假设我正在编写一个聊天机器人(不和谐、电报等)。机器人可以处理聊天命令(例如 !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...对我来说,这看起来像是一种不好的做法和代码味道。有更好的方法吗?
查看完整描述

3 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

您可能希望依赖 a Mapof Commands。

我会明确指出,对于这个用例,使用FunctionorSupplier或任何标准功能接口根本不是惯用的。躲开它。


我们可以从构建一个Command接口开始


interface Command {

   Result execute(); 

}

或者如果你需要接受一个论点


interface Command {

   Result execute(final Input input); 

}

哪个将具有所需的实现


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 {

   COMMANDS.put("join", new JoinCommand());

   COMMANDS.put("leave", new LeaveCommand());

   // 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(

   "join", new JoinCommand(), 

   "leave", new LeaveCommand(),

   // And so on.

)


查看完整回答
反对 回复 2022-07-27
?
郎朗坤

TA贡献1921条经验 获得超9个赞

通常,它是通过映射实现的。用 simple 实现这一点会更加清晰易读Map。


例如:


Map<String, Command> strategies = new HashMap<String, Command>(){{

  put(JOIN_MESSAGE, new JoinCommand());

  put(LEAVE_MESSAGE, new LeaveCommand());

}};

及其用法:


Command command = strategies.get(messageType);

此外,如果您需要根据某些参数构造命令,则可以从 Java 8 开始定义创建策略(工厂)。


Map<String, Function<String, Command>> strategies = new HashMap<String, Command>(){{

  put(JOIN_MESSAGE,  param -> new JoinCommand(param));   // or JoinCommand::new

  put(LEAVE_MESSAGE, param -> new LeaveCommand(param));  // or LeaveCommand::new

}};

及其用法:


Command command = strategies.get(messageType);

command.process(param);


查看完整回答
反对 回复 2022-07-27
?
大话西游666

TA贡献1817条经验 获得超14个赞

您好,您尝试使用 Switch Case 语句,它很容易理解,并且将来如果您有任何更改,那么很容易更新代码。


switch(message)

    {

       case JOIN_MESSAGE:

            return new JoinCommand();

            break;


       case LEAVE_MESSAGE:

            return new LeaveCommand();

            break;

    }


查看完整回答
反对 回复 2022-07-27
  • 3 回答
  • 0 关注
  • 81 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信