基于String的对象创建

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于String的对象创建相关的知识,希望对你有一定的参考价值。

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

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

String userMessage = getTheMessageTextSomehow();
// Do something with the  message.

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

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

最简单的方法是拥有一个大型CommandFactory或任何类somwhere,就像这样

if(message.equals(JOIN_MESSAGE) {
    return new JoinCommand();
} 
if(message.equals(LEAVE_MESSAGE){
    return new LeaveCommand();
}
//etc...

这看起来像是一种糟糕的做法和代码味道。有没有更好的方法呢?

答案

你可能想依靠MapCommands。 我将清楚地表明,对于这个用例,使用FunctionSupplier,或任何标准功能界面都不是惯用语。躲开它。

我们可以从构建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(实现)数据结构中。一个Map是完美的。

因为你的命令定义将是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.
)
另一答案

通常,它是通过映射实现的。用简单的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);
另一答案

您好,您可以尝试使用Switch Case语句,它很容易理解,将来如果您有任何更改,则可以轻松更新代码。

switch(message)
    {
       case JOIN_MESSAGE:
            return new JoinCommand();
            break;

       case LEAVE_MESSAGE:
            return new LeaveCommand();
            break;
    }

以上是关于基于String的对象创建的主要内容,如果未能解决你的问题,请参考以下文章

如何将代码片段存储在 mongodb 中?

java Ftp上传创建多层文件的代码片段

创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)减速(车速自减)修改车牌号,查询车的载重量。 编写两个构造方法:一个没有(代码片段

Android - 如何将自定义对象传递给片段

Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段

有没有办法使用相同的布局动态创建片段并向它们显示数据?