我们都从根本上了解Constructor
和用户定义的Initialize()
方法之间的区别。
我的问题集中在对象创建的最佳设计实践上。我们可以将所有Initialize()
代码放入Constructor()
,反之亦然(将所有预热代码移至Initialize
方法,并从Constructor
调用此方法。)
目前,在设计新课程时,我会在constructor()
中创建任何新实例,并将任何其他预热代码移至Initialize()
方法。
您认为最好的权衡点是什么?
答案 0 :(得分:25)
我认为应该考虑多个方面:
构造函数应该以一种处于可用状态的方式初始化对象。
构造函数应该只初始化一个对象,而不是执行繁重的工作。
构造函数不应直接或间接调用虚拟成员或外部代码。
因此,在大多数情况下,不需要使用Initialize方法。
如果初始化涉及的不仅仅是将对象置于可用状态(例如,当需要执行繁重的工作或需要调用虚拟成员或外部时),则初始化方法是个好主意。
答案 1 :(得分:3)
我最近发现自己在考虑这个问题(因此找到了这个问题),虽然我没有答案但我认为我会分享我的想法。
this.member = member;
在我看来,这与IoC,继承,测试非常吻合,只是闻起来很好。
然而,有时需要举重,所以我一直想做的是:
这意味着将初始化代码抽象到另一个类并将其传入。这通常可能是因为繁重的工作并不是您的对象责任,所以这样做实际上可以重构更好的代码。
如果这是不可能的,并且您确实需要在使用前初始化您的类的状态,那么添加一个initialse方法。这确实会在代码中添加时间依赖性,但这并不一定是坏事,尤其是在使用IoC容器时:
说CarEngine
需要DrivingAssistComputer
,DrivingAssistComputer
需要进行大量初始化,即加载所有参数,天气状况检查等。另外需要注意的是{{1}不直接与CarEngine
交互,它只需要它存在,在侧面做自己的事情。事实上,如果没有DrivingAssistComputer
在后台做某事(在某处改变一些状态),引擎可能无法正常工作。如果我们使用IoC,那么我们有:
DrivingAssistComputer
所以我们这里有一个构造函数参数,将// Without initialise (i.e. initialisation done in computer constructor)
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// No need to reference computer as we dont really interact with it.
}
...
标记为依赖,但实际上并未使用它。所以这很难看,但我们添加一个Initialise方法:
computer
仍然不是一个有凝聚力的类,但至少我们知道我们依赖于计算机,即使我们没有在构造函数之外直接与它进行交互。
另一个选择是使用CarEngineFactory:
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// This ofcourse could also be moved to CarEngine.Initialse
computer.Initialise();
}
...
但是,我发现工厂和IoC只是混淆矩阵,所以我会选择第二种选择。
很想听听有关这方面的一些想法。
编辑1: 我错过的另一个选项是使用Initialise方法,但将此调用移至IoC初始化模块。因此创建和初始化仍然有些封装。