制作所有字段final
通常都是一个好主意,但有时我发现自己在构造函数中做了所有事情.最近我最终得到了一个类,它实际上构建了构造函数中的所有内容,包括读取属性文件和访问数据库.
一方面,这就是该类的用途,它封装了读取的数据,我喜欢创建完全初始化的对象.构造函数并不复杂,因为它委托了大部分工作,所以它看起来很好.
另一方面,感觉有点奇怪.此外,在大约17:58的这次演讲中,有充分的理由不在构造函数中做很多工作.我想我可以通过传递适当的假人作为构造函数参数来消除这个问题.
问题仍然存在:构建器中的大量工作(甚至是所有工作)都不好吗?
Emi*_* L. 37
...只要您不违反单一责任原则(SRP)并坚持使用依赖注入(DI).
我一直在问自己这个问题.反对在我找到的构造函数中工作的动机是:
...如果你的构造函数需要为它工作以遵守资源获取初始化(RAII)并且该类没有违反SRP并且DI被正确使用; 然后在构造函数中工作就是A-Okay!如果您想要防止使用完全初始化失败的类对象而不依赖于用户检查某些返回值,您甚至可以抛出异常.
Dav*_*nco 18
这是一个非常开放的问题,所以我的答案将尽可能一般......
在构造函数中工作并不像几年前那样"糟糕",因为异常处理并不像今天那样普遍和发展.您会注意到Google Tech的演讲主要从测试角度来看构造函数.构造函数在历史上一直非常难以调试,所以说话者是正确的,在构造函数中尽量少做更好.
话虽如此,你会注意到他还涉及依赖注入/提供者模式,这种模式因复杂的构造函数而臭名昭着.在这种情况下,首选保留构造函数中的提供者/ DI代码.同样,答案取决于您使用的模式以及您的代码如何"适合"在一起.
使用构造函数的全部目的是创建一个可以立即使用的整洁对象; 即new Student("David Titarenco", "Senior", 3.5)
.没有必要这样做,david.initialize()
因为它完全是愚蠢的.
这是我的一些生产代码,例如:
Config Conf = new Config();
Log.info("Loading server.conf");
Conf.doConfig();
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我决定不对构造函数做任何事情(它是空的)但是有一个doConfig()
方法可以完成所有的磁盘i/o; 我经常认为该doConfig()
方法毫无意义,我应该在构造函数中做所有事情.(毕竟我只查看配置文件一次.)
我认为这完全取决于你的代码,你不应该认为在构造函数中添加"东西"是件坏事.这就是构造函数的用途!有时,当真正所有类需要做的是加载配置文件时getThis
,我们会被OOP(,, )带走.在这种情况下,只需将所有内容放在构造函数中并将其称为一天!setThat
doBark
Mau*_*res 13
通常情况下,如果您的对象具有复杂的创建算法,您可以使用Builder或Factory简化它.特别是如果有要验证的前置条件来构建对象.
一旦使用建筑工地和工厂你开始建立你的对象,他们可以验证前置和后置条件,使你的代码的确定客户端将只能够访问一个完全初始化的对象,而不是一个半造一个,你甚至可以用时下在流行的流畅界面中创建您的对象并使其看起来很酷; D
new EmailMessage()
.from("demo@guilhermechapiewski.com")
.to("destination@address.com")
.withSubject("Fluent Mail API")
.withBody("Demo message")
.send();
Run Code Online (Sandbox Code Playgroud)
显然这不是你的情况,因为这不是使用Builder,但它很像你可以构建的东西,以使你的构造函数减少工作并使你的代码看起来更简单.
pcj*_*zer 11
当我在构造函数中放入太多代码时,我遇到了以下问题:
所以是的,在我看来,在构造函数中做很多事情是个坏主意.
通常我只是将一些字段初始化放入构造函数中,并在每个人都加入时调用init方法.