Java 构造函数注入,可测试性设计

Java 构造函数注入,可测试性设计,java,testability,constructor-injection,Java,Testability,Constructor Injection,我有这段代码(您可能可以忽略它是Swing代码),但我的构造函数中通常会有太多的参数。我应该使用模型bean类,然后在构造函数中传递该对象吗 public BrowserFrame(final JTextField url, final JTextArea response, final JTextField command, final JButton actionButton) { this.urlField = url; this.responseArea = respo

我有这段代码(您可能可以忽略它是Swing代码),但我的构造函数中通常会有太多的参数。我应该使用模型bean类,然后在构造函数中传递该对象吗

public BrowserFrame(final JTextField url, final JTextArea response, final JTextField command, final JButton actionButton) {

    this.urlField = url;
    this.responseArea = response;
    this.commandField = command;
    this.actionButton = actionButton;

}     
在这段代码中,我正在考虑添加更多的对象,供这个类使用。我是否继续添加更多参数并将它们传递到构造函数中。可能使用凝固注射吗

但据Misko说,这也是代码气味


“对象被传入,但从未直接使用(仅用于访问其他对象)”

既然您希望清理代码并提高其可测试性,那么您可以进行setter初始化。这样,您的对象就有了一个更干净的构造函数。如果只设置代码的“部分”字段而不是全部字段,那么测试代码也会更容易。测试变得更具可读性


值得研究Spring,因为即使您不使用它,您也可以从该框架的指导方针中获益。

BrowserFrame
倾向于表示您正在扩展一个不需要的类(
JFrame
)。那太糟了

我倾向于在
JComponent
/视图层上设置布局层

class ThingView {
    [...]
    public JTextField /*or JComponent*/ createURL() { /* or geURL */
        return new JTextField(...); // Or from a field if using get.
    }
    [...]
}

class ThingLayout {
    private final ThingView view; 
    [...]
    public JPanel createBrowsePanel() {
        JPanel panel = new JPanel();
        [...]
        panel.add(view.createURL());
        [...]
        return panel;
    }
}

构造函数中的参数太多表明类的职责太多。如果只是在构造函数中设置字段,请查看这些字段中的某些字段是否仅由类中的方法子集使用。这表明你的参数和方法可以分成更小的类,责任更集中。

同意比尔的观点,这可能表明责任太多。但是,如果你真的不能完成这些职责,这是清理繁忙的构造函数/方法的一种方法

我认为我们不应该忽视这是swing代码。GUI以有组织的方式聚合多个不同的对象。如果您发现自己支持多个构造函数,我建议您认真考虑重构,因为理解什么是非必要的将是非常混乱的。但是,如果要将七个组件放入某个组织模板中,那么在构造函数中完成这一切并不一定是一个坏主意,前提是每个参数的作用都是明确的


如果问题是“这个类有太多关注点吗?”停止问“一个类有太多关注点的迹象是什么?”为什么不问“这个类的关注点是什么?”如果答案很简单,比如“它将多个表单元素组织到一个视图中”,这就是我(以及其他浏览代码的人)所说的从逻辑上假设,然后停止担心构造器之类的化妆品。在这种情况下很明显。添加更多的类只会混淆这一点。

这个问题被定义为一个创造性/机械性的问题,但正如许多以前的答案所指出的,这实际上是一个设计问题

我认为从长远来看,重新评估对象组合方案可能更有用,例如重新调整抽象,使BrowserFrame由部分(例如,AddressSection、ActionSection、InputSection、FeedbackSection等)而不是单个Swing对象组成


您还可以使用子分类来重构BrowserFrame结构的过度参数化。

我的意思是让你们忽略spring组件。您所采取的方法将取决于上下文。这种方法并不特定于Swing,但Swing是一个大型用例,也是您正在使用的一个。我想在“swing”中,我可能可以使用setter注入,但在正常的对象世界中,我应该解决我的问题。在这种情况下,有很多参数,但似乎类没有太多的责任(忽略隐含的继承)。@Tom:在给出参数列表的情况下,不,它似乎没有太多的责任,但OP说他会增加更多。如果这些都是Swing组件,那么您仍然是对的。