我应该在构造时加载 Java 对象的数据,还是通过方法调用显式加载?
这是一个设计问题。我正在尝试在两种实现之间做出决定。
为了正确解释这一点,我需要一个例子。因此,举个例子:
我有一个类可以生成有关特定日期的某些股票市场价值的报告。我创建一个 StockMarketReportGenerator
对象,向其传递今天的日期,然后它会根据今天的市场价值生成一份报告。
StockMarketReportGenerator
“有一个”StockMarketData
对象。 StockMarketData
对象的用途是包含存储在数据库表(可能称为 StockMarket :) )中的所有股票市场值,以及根据表数据计算出的一些其他值。它具有与数据库连接、检索数据、执行必要的计算并将最终值存储在对象的成员变量中的私有方法。 (然后它有 getter 方法来公开这些值,但没有 setter 方法。)StockMarketData 类基本上是股票市场数据值的“持有者”。我有一个名为“calculateStockMarketData()
”的中央函数,它调用所有这些私有帮助器方法并设置对象。 (我知道所有这些处理确实可以通过 Hibernate 之类的框架更轻松地处理;但决定手动完成,因为它是一个非常小的、有点临时的项目,不值得设置。)
我的问题是这样的- 在我的 ReportGenerator
类中,我只需要 StockMarketData
对象即可访问它的属性/ 成员变量 - 后处理和后计算。这意味着我真的想预先填充对象 与数据。因此,我将 calculateStockMarketData
方法保留为私有,并从 StockMarketData
自动调用它 构造函数。但我对在构造函数中进行所有处理然后没有任何公共方法感到有点不安。这是设计缺陷吗?或者这真的是最合乎逻辑的方法吗?基本上,以下 2 个实现哪个更好?
1) (我当前的实现)将中央 calculateStockMarketData()
方法设为私有,并从 StockMarketData
方法构造函数调用它(传递今天的日期),以便每当您有 < code>StockMarketData 对象,它已经被填充。因此,在开始使用对象属性之前,我需要从 ReportGenerator
类中获取以下行:
StockMarketData myData = new StockMarketData(someDate);
2) 将中央 calculateStockMarketData()
方法公开,以便设置一个您需要显式调用该方法的 StockMarketData
对象。因此,我将在 ReportGenerator
类中编写代码:
StockMarketData myData = new StockMarketData(someDate);
myData.calculateStockMarketData();
第一个让我觉得是更好的设计,特别是因为在初始化之前不可能使用对象属性。但我也不确定从构造函数执行大量代码的标准......我应该选择哪个?
This is a design question. I'm trying to decide between 2 implementations.
In order to properly explain this I need an example. So, for the sake of example:
I have a class that generates a report about, let's say, certain Stock Market values on a specific day. I create a StockMarketReportGenerator
object, passing it today's date, and it generates a report based on today's market values.
The StockMarketReportGenerator
"has a" StockMarketData
object. The purpose of the StockMarketData
object is to contain all the stock market values that are stored in a table (probably called StockMarket :) ) in the database, and some further values calculated from the table data. It has private methods that connect with the database, retrieve the data, do the necessary calculations, and store the final values in the object's member variables. (It then has getter methods to expose these values, but no setter methods.) The StockMarketData
class is basically a "holder" for stock market data values. I have one central function called something like "calculateStockMarketData()
" that calls all these private helper methods and sets up the object. (I am aware that all this processing could really be more easily handled by a framework such as Hibernate; but the decision was made to do it manually as it's a very small, somewhat temporary project and not worth the setup.)
My question is this - from my ReportGenerator
class, I only need the StockMarketData
object in order to access it's properties /
member variables - post-processing and post-calculations. Which means that really, I want to get the object pre-filled
with data. And so I keep the calculateStockMarketData
method private and call it automatically from the StockMarketData
constructor. But I'm feeling somewhat uneasy about doing all my processing in a constructor and then not having any public methods. Is this a design flaw? Or is it really the most logical way to do this? Basically, which of the following 2 implementations is better?
1) (My current implementation) Make the central calculateStockMarketData()
method private and call it from the StockMarketData
method constructor (passing today's date), so that whenever you have a StockMarketData
object, it's already filled. So all I would need from the ReportGenerator
class before I start using the object properties is the line:
StockMarketData myData = new StockMarketData(someDate);
2) Make the central calculateStockMarketData()
method public, so that in order to set up a StockMarketData
object you need to explicitly call the method. So from the ReportGenerator
class I would code:
StockMarketData myData = new StockMarketData(someDate);
myData.calculateStockMarketData();
The first strikes me as the better design, especially since there is then no possibility of using the object properties before they are initialized. But I am also unsure about the standards regarding executing a great deal of code from a constructor... Which should I choose?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Martin Fowler 写了一篇关于依赖注入(构造函数与 Setter 注入) 的好文章。他的建议是“尽可能在构造时创建有效的对象”。
IMO,如果可能的话,最好构造有效的对象,因为这样可以更轻松地阅读/观察代码的行为,因为您可以假设对象已正确构造,并且与未正确填充对象相关的错误较少。 setter 与构造函数注入的问题与您所询问的问题不同,这是一个在哪里执行业务逻辑的问题。我认为最好使用构造函数来创建有效的对象,然后在另一个公共方法(您的#2)中执行实际的业务逻辑,以便对象的构造可以在与实际业务逻辑不同的时间发生。
Martin Fowler has written a good essay on dependency injection (Constructor vs. Setter injection). His advice is "as much as possible, to create valid objects at construction time".
IMO, It's best to construct valid objects if possible, because it makes it easier to read/observe the behavior of the code, since you can assume that the objects were constructed properly, and you have less bugs related to objects not being filled in properly. The issue of setter vs. constructor injection is different from what you are asking about though, which is a matter of where to execute your business logic. I think it is best to use the constructor for creating a valid object and then execute the actual business logic in another public method (your #2), so that the construction of the object can happen at a different time than the actual business logic.
我会选择第二个,特别是如果有可能向类添加不依赖于该数据的方法。
另一方面,如果您认为类在没有填充数据的情况下处于无效状态,则应该在构造时执行此操作。
I would go with number 2, especially if there is a possibility of adding methods to the class that don't rely on that data being there.
On the other hand, if you would consider the class to be in an invalid state without the data populated, you should do it on construction.
我总是在构建后显式加载。
从构造函数调用数据库可能会导致调试困难、代码更加脆弱、不灵活,并且如果对象的使用发生变化,还会导致性能问题。
I always load explicitly, post-construction.
Calling a database from a constructor can make for difficult debugging, more fragile, inflexible code, and cause performance problems if your usage of the object changes.
一个好的做法是不要在构造函数内执行大量代码。
A good practice is to not execute a lot of code inside a constructor.