在这样的构造函数中调用init方法是违反Clean Code的吗?

我在下面的代码中关注的是构造函数的参数实际上并没有直接映射到类的实例字段。 实例字段从参数中获取值,并且我正在使用initalize方法。 此外,我做了一些事情,以便创建的对象可以直接在后面的代码中使用,例如调用drawBoundaries()。 我觉得它正在做一个抽象意义上创建(初始化)Canvas的意思。

我的构造函数做得太多了吗? 如果我添加方法从外部显式调用构造函数中的东西,那就错了。 请让我知道你的看法。

public class Canvas { private int numberOfRows; private int numberOfColumns; private final List listOfCells = new LinkedList(); public Canvas(ParsedCells seedPatternCells) { initalizeCanvas(seedPatternCells); } private void initalizeCanvas(ParsedCells seedPatternCells) { setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells); drawBoundaries(); placeSeedPatternCellsOnCanvas(seedPatternCells); } ... 

PS:对不起,如果这看起来像个愚蠢的问题; 我的代码将由OOP大师审核,我只是担心:-0

编辑:

我读了一些关于initalizeCanvas()被覆盖的方法的担忧 – 幸运的是这些方法是私有的,不会调用任何其他方法。

无论如何,经过对网络的进一步研究,我开始喜欢这个…我希望你们同意!! ??

 public class Canvas { private int numberOfRows; private int numberOfColumns; private final List listOfCells = new LinkedList(); private Canvas() { } public static Canvas newInstance(ParsedCells seedPatternCells) { Canvas canvas = new Canvas(); canvas.setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells); canvas.drawBoundaries(); canvas.placeSeedPatternCellsOnCanvas(seedPatternCells); return canvas; } 

构造函数包含非平凡代码通常是个坏主意。 通常,构造函数最多应将提供的值分配给字段。 如果对象需要复杂的初始化,那么初始化应该是另一个类(通常是工厂 )的责任。 请参阅MiškoHevery关于此主题的精彩文章: 缺陷:构造函数执行实际工作 。

你永远不应该在构造函数中调用非final方法。 有效的Java可以很好地解释原因,但基本上你的对象在构造函数返回之前不处于稳定状态。 如果构造函数调用被子类覆盖的方法,则可能会出现奇怪的,未定义的行为。

另见这个答案 。

虽然它不是最优雅的方式,但从OO的角度来看,我并不认为它有缺陷。 但是,如果您没有从类中的任何其他位置调用private方法initalizeCanvas ,那么您可以考虑将这三行移动到构造函数本身。

我看到两个潜在的问题:

  • 您在initializeCanvas调用的方法是私有还是最终? 如果不是,则子类可能会覆盖它们并且无意中破坏了构造函数。

  • 你在drawBoundaries方法中做图形操作吗? 构造函数只执行创建有效对象所需的最小值是一种很好的做法。 canvas是否必须具有有效的初始状态?

这取决于。

如果私有方法不调用可以被覆盖的其他方法,那么构造函数调用私有方法也不错。 但是,如果可以覆盖它调用的方法或其中一个方法,则可能会遇到麻烦。 具体来说,覆盖方法将在重写类构造函数运行之前调用,并且在初始化之前将看到实例字段。

第二个问题,如果你的initalizeCanvas方法中的一些方法看起来像我们在完全初始化之前“发布”当前对象。 如果应用程序是multithreading的,则可能会出现问题,并且可能导致其他线程看到过时的字段值。

如果您有多个构造函数,其中某些参数是默认的或推断的,则私有init函数可能很有用。 确定所有内容后,一个私有init函数会填充该对象。

在一个构造函数类中,可能不是。