在构造函数中执行类的主要工作有什么问题吗?

sle*_*ske 12 java constructor coding-style

我一直认为,一般来说,类的主要工作应该在其实例方法中完成,而构造函数应该只将实例置于可用的初始状态.

但我发现在实践中有些情况下,将基本上所有实际工作放入构造函数似乎更有意义.

一个例子:我需要从数据库中检索一些特定于DBMS的信息.对我来说最自然的方式似乎有一个类DBMSSpecInfo,带有一个构造函数:

public DBMSSpecInfo(java.sql.Connection conn) throws SQLException{
  // ... retrieve info from DBMS
}

/** @returns max size of table in kiB */
public int getMaxTableSize() {//...}

/** @returns max size of index in kiB */
public int getMaxIndexSize() {//...}

/** @returns name of default schema */
public String getDefaultSchema() {//...}
Run Code Online (Sandbox Code Playgroud)

您将构造一次类,构造函数将获取所有数据,然后您可以使用各种getter来检索所需的信息.

当然我可以将方法放在其他地方,并且只DBMSSpecInfo用于返回值(实际上只使用DBMSSpecInfo作为值持有者),但是创建一个类只是为了从单个函数返回值感觉很难看.

所以你怎么看?在构造函数中执行主要工作是否有问题?它在Java中是"非惯用的"吗?或者这是一种可接受的(虽然可能不常见)的做法?

Boz*_*zho 10

主要的实际问题是单元测试 - 如果不进行实际工作,您将无法实例化对象.(或者你必须模拟参与这项工作的所有课程).

相关说明:面向可测试性的OO设计.它给出了为什么在构造函数中工作不利于单元测试的示例.


Pét*_*rök 6

在这种情况下,我更希望将创建代码与类本身分开.它可以放入静态工厂方法或单独的工厂类(也可以是公共静态内部类).选择取决于代码的复杂性和设计上下文(在这种情况下我们不知道).

这也允许您进行优化,例如缓存和重用类实例.


Car*_*icz 5

我很注重实用主义.如果它有效,那就去做吧!但是,为了纯洁和善良的名义,我想提出一个设计建议:

这个类使用检索它的机制混淆了数据内容.您最终在其他地方使用的对象仅对其包含的数据感兴趣.因此,"干净"的事情是使用不同的类来挖掘信息,然后创建此属性对象的实例.

另一个类可能有更长的生命周期,因为你通常会调用一个方法来完成工作,而不是构造函数.DBMSSpecInfo可能的构造函数最终会分配一堆属性但不会执行大量具有错误功能的数据库访问工作.


Dum*_*y01 4

在您的示例中,我将创建一个静态方法GetDBMSSpecInfo(java.sql.Connection conn),如果出现问题(如果您不想引发异常),它将返回DBMSSpecInfo对象的实例或 null。

对我来说,DBMSSpecInfo 对象不应该只包含获取属性:MaxIndexSize、MaxTableSize、DefaultSchema 等。

我会将这个对象的构造函数设为私有,以便只能从静态方法创建实例。