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