【问题标题】:Return class based on enum input基于枚举输入的返回类
【发布时间】:2015-05-06 18:44:09
【问题描述】:

我有一个为游戏服务器运行的 Socket 网络。为了简化相互发送数据,我想使用枚举作为构造函数的输入,并使用基于该枚举值的构建方法。

例如,我有一个枚举:

enum DataType {
    connectPlayer,
    returnServerState;
}

现在我有一个名为 BuildData 的构造函数:

private DataType dataType;

public BuildData(DataType dataType) {
    this.dataType = dataType;
}

我的问题是:我希望能够根据 DataType 使用具有不同输入的构建方法。

例如,如果我有 DataType 'connectPlayer',我想要一个具有以下输入的构建方法:

public String build(String UUID, String server) {
    return "connectPlayer:" + UUID + ":" + server;
}

但是,当 DataType 是 returnServerState 时,我希望它是这样的:

public String build(String thisServer, String serverState) {
    return "setServerState:" + thisServer + ":" + serverState;
}

冒号放在中间,所以我可以对它们使用 split 方法。

我的问题是:我是否必须根据包含正确方法的枚举类型返回一个类实例,还是有更简单的方法来做到这一点?

谢谢!

【问题讨论】:

  • 也许使用您的 DataType 作为您方法的附加参数。 String build(String s1, String s2, DataType dt)
  • 您的 build() 方法是否总是接受相同类型的参数(例如 build(String, String))?也就是说,无论DataType如何,构建方法签名都相同吗?
  • 对不起@pens-fan-69,忘了提。不,它有时会接受更多的参数,有时会接受更少的参数,具体取决于枚举类型。
  • 对于您的情况,您几乎可以肯定希望创建一个丰富的枚举类型,并使用特定的常量方法来生成和返回所需的对象。此外,由于您希望控制创建的对象的类型,因此使用静态工厂方法而不是构造函数(必须返回自己的类型)来构建对象会很有用。
  • "冒号放在中间,所以我可以对它们使用拆分方法。"这通常是糟糕设计的标志。您应该尝试将此数据表示为对象中的实例字段。

标签: java class input constructor enums


【解决方案1】:

如果您所有的build 方法只是在参数数量上有所不同,但具有相同的参数类型和返回类型,您可以使用接受varargs 的方法,如下所示:

String build(String... args)

此外,您应该看看enum API,因为 java 枚举不仅仅可以枚举值。

您可以按如下方式扩展您的枚举:

enum DataType {
  connectPlayer {
    @Override
    public String build(String... args) {
      if (args.length != 2) throw new IllegalArgumentException("wrong number of arguments");
      String UUID = args[0];
      String server = args[1];
      return "connectPlayer:" + UUID + ":" + server;
    }
  },
  returnServerState {
    @Override
    public String build(String... args) {
      // do something else here...
      return "returnServierStateArgs " + Arrays.toString(args);
    }
  };

  public abstract String build(String... args);
}

用法:

System.out.println(DataType.connectPlayer.build("first", "second"));
System.out.println(DataType.returnServerState.build("first", "second", "...", "more"));

// prints:
// connectPlayer:first:second
// returnServierStateArgs [first, second, ..., more]

或者,您可以创建一个interface 并为不同的DataTypes 实现它。

interface Builder {
  String build(String... args);
}

【讨论】:

  • 感谢大家的帮助!这是我决定使用的解决方案。
  • 这基本上是我的回答变得更加冗长......干得好@tomse
【解决方案2】:

我的问题是:我是否必须根据包含正确方法的枚举类型返回一个类实例,还是有更简单的方法来做到这一点?

您无法控制构造函数实例化的对象类型。所以你不能在那个时候做出决定。您似乎正在寻找的是一个工厂,它将根据您的 DataType 返回适当的对象。但是,我认为这对您没有帮助,因为您需要基于类型的不同 build() 方法签名。您需要考虑您没有以非常正确的方式解决问题的可能性。具体来说,您想要的是多态地“构建()”一条消息。这是一个超出此问题答案范围的讨论。

【讨论】:

  • 如果我正确理解目标,我建议您考虑使用 build()(或者更好的是,serialize() 或 marshall())方法创建一个“消息”接口没有论据。消息应包含实例变量以及将其序列化到网络所需的信息。这可以放在一个队列中,让工作人员发送出去。
  • 对上述评论的一个更正,而不是说“消息应该包含......”我的意思是说,“实现消息接口的类应该包含......”
【解决方案3】:

我建议创建一个工厂,它会根据你的枚举值为你提供一个类的实例,就返回类型而言,你想要返回的所有类实例类型都声明一个接口,该接口将由你所有的类,这样返回类型就是那个接口。

例如:

Class Factory{
    public BaseInterfaceName getInstaceBasedOnEnum(DataType d){
        BaseInterfaceName name;
        switch(d)
        case q:
        name = instanceBasedOn D;
        break;
    }
}

根据数据类型获取实例的其他类的结构

public class xyz implements BaseInterfaceName;
public class abc implements BaseInterfaceName;

【讨论】:

  • 很遗憾,他不能这样做,因为他需要为每种数据类型提供不同的方法签名。
  • 他需要根据每个输入在正确的类中声明正确的方法,该方法他可以在接口中声明并根据用例的需要重载或覆盖它。
【解决方案4】:

我不知道你的架构等等,但是像这样将构建方法放在枚举类中可能会有用吗?

public enum DataType {
CONNECTPLAYER{

    @Override
    public String build(String... strings) {
         return "connectPlayer:" + strings[0] + ":" + strings[1];
    }

},
RETURNSERVERSTATE{

    @Override
    public String build(String... strings) {
        return "setServerState:" + strings[0] + ":" + strings[1];
    }

};

public abstract String build(String...strings);
}

如果在枚举类中包含构建方法不是问题,那么它似乎是一个非常巧妙的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 2022-06-11
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多