【问题标题】:Java, enum with constructorJava,带有构造函数的枚举
【发布时间】:2015-08-22 19:58:06
【问题描述】:

我正在重构一些用 Java 编写的遗留系统,但遇到了枚举构造函数的问题。

我有一个这样的枚举类(只是一个例子):

public enum Signal{
   ON(new InButton()),
   OFF(new OutButton())

   private final Button button;

   Signal(Button button) {
       this.button = button;
   }
}

InButton 和 OutButton 扩展了 Button 接口。

第一次使用 Signal.Values() 方法访问枚举值。 (另外,在一个Button方法中,我有一个使用枚举的代码,比如activateButton(Signal.ON))

在重构代码时,我想为 Button 创建一个新的构造函数来表达它的依赖关系,例如 Button(String input)。

问题是我不知道如何将新参数传递给枚举按钮字段。 处理这种情况的正确方法是什么? 是否应该使用这个枚举?


Jean Logeart 问题后的澄清:InButton 和 OutButton 也有一个带有 String 参数的构造函数。 我宁愿避免将其初始化为 null,因为它可能会产生其他问题。

基本上这个问题是如何使用 java 语法模仿 a=f(x) 。大多数时候我可以做到:

  1. y = 新 x(); a = 新 f(y);
  2. a = 新 f(新 x());
  3. a = 新 f(null); a.getF().setX(new x());

在这种情况下我做不到。

【问题讨论】:

  • 我想说这部分代码根本不需要重构。它是 Signal 枚举中 Singleton 的实现。
  • @LuiggiMendoza,嗨 - 这更像是 Jean Logeart 在他的回答中描述的第一个选项,因此没有值的默认构造函数在 InButton 和 OutButton 中不再有效。
  • 这不是对代码的重构,而是简单的维护。这就是显而易见的解决方案。
  • @LuiggiMendoza 我想重构 InButton 和 OutButton 类以表达它们的依赖关系并为它们创建测试用例。也许你对语义的看法是对的,无论如何它在枚举类中产生了一个问题;)

标签: java enums refactoring


【解决方案1】:

我建议根本不让枚举知道按钮。让他们列举可能的信号,然后将映射信号->按钮的工作放在其他地方:

Function<Signal, Button> signalToButton = ...

这也将更容易注入不同的按钮进行测试;例如,您可以注入一个模拟的 Button 来确认我们没有按下它。

就在代码中使用该映射而言:您可以“安装”到某个静态字段的映射,或者更好的是,将其作为构造函数参数提供给任何需要它的代码。依赖注入对于后一种选择非常有帮助,但这可能是一个更大的变化。

【讨论】:

  • 听起来是一个合理的解决方案。我只是希望有一种更优雅的方法可以使用 java 语法来模仿 a=f(g(x)) 。大多数时候我可以定义 y = new g(x) 而不是 a = new f(y),或者 a = new f(new g(x));在这种情况下,我做不到。
【解决方案2】:

两个主要选项。

第一个 InButton 和 OutButton 也有一个带有 String 参数的构造函数,在这种情况下,您需要在实例化时提供 String:

public class InButton extends Button {
    public InButton(String s) {
        super(s);
    }
}
// ...
public enum Signal{
    ON(new InButton("in"))
    // ...
}

第二个选项,InButton 和 OutButton 用特定的 String 实例化,在这种情况下,enum 中不需要重构:

public class InButton extends Button {
    public InButton() {
        super("in");   // default value
    }
}
// ...
public enum Signal{
    ON(new InButton())   // same as before
    // ...
}

【讨论】:

  • 第一个选项是正确的,但是这个输入字符串在编译时是未知的,它是程序在访问 Signal.Values() 之前初始化的参数 - 例如使用属性文件中的值。
  • 默认为null并添加一个setter怎么样?
  • 有点棘手,button类中的一些方法可以随时被外部客户端访问,也就是说Button的创建必须一步完成,不能暴露部分Button .
猜你喜欢
  • 2011-08-20
  • 1970-01-01
  • 2016-07-17
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
相关资源
最近更新 更多