Java对象字段值取决于其他字段-最佳实践模式?
我有一个简单的java对象Java对象字段值取决于其他字段-最佳实践模式?,java,oop,Java,Oop,我有一个简单的java对象 public class Order { private int quantity; private long price; private long totalPrice; } 我将只存储数量和价格,totalPrice字段将根据数量*价格生成 现在我在Order类中有了名为populateTotalPrice()的方法。但我似乎把一个逻辑放在一个实体类中,它可能是一个反模式 我的另一个选择是使用helper静态方法 这种行为的最佳实践是什么?是的
public class Order {
private int quantity;
private long price;
private long totalPrice;
}
我将只存储数量和价格,totalPrice字段将根据数量*价格生成
现在我在Order类中有了名为populateTotalPrice()的方法。但我似乎把一个逻辑放在一个实体类中,它可能是一个反模式
我的另一个选择是使用helper静态方法
这种行为的最佳实践是什么?是的,创建发票时不必将总价放在订单中
总价是在创建发票的过程中计算出来的。Java实践是根据属性而不是字段来处理对象。大多数属性基于支持字段,但在您的情况下,将属性
totalPrice
作为计算属性是有意义的:
public long getTotalPrice(){
退货价格*数量;
}
在实体中有一个totalPrice
字段,其中值是其他字段值的函数,这与数据库的非规范化思想密切相关。(从您对其他答案所做的一些评论中,我推断您正在将此实体与要查询的支持数据库表一起使用。)特别是,它违反了3NF:列值应仅依赖于键列值。虽然存储计算值违反了3NF,但有时这样做有很好的性能原因。与数据库一样,有多种方法来处理这种类型的需求
您也许可以将问题转移到数据库,并从Java对象中删除totalPrice
字段。根据所使用的DBMS,一种可能性是将数据库模式定义为具有计算列。(计算列不是标准SQL,但有几个系统(如Microsoft的SQL Server)支持它们。)另一种可能性是定义数据库视图(存储在数据库中并像查询另一个表一样查询的SELECT
语句)。视图可能类似于:
CREATE OR REPLACE VIEW orders_view AS
SELECT quantity, price, quantity * price AS total_price
FROM orders
然后,当需要使用totalPrice
(或totalPrice
)时,您的代码可以查询orders\u视图
,而不是orders
最后,您可以在执行过程中对实体进行反规范化,并接受结果,主要原因是更新异常:您更新了price
和/或quantity
,但未能更新totalPrice
字段。您可以通过在数量
和价格
的设置器中更新总价
来降低此风险(而不是使用单独的populateTotalPrice()
方法):
请注意,totalPrice
没有设置器。以这种方式安排代码可以确保不调用populateTotalPrice()
而不会遇到问题。(当然,如果您可以在不经过Java对象的情况下更改数据库值,那么最终仍然会出现更新异常。)
在某些框架中,您可以在每次从表中加载实体时执行这些计算。(例如,Hibernate具有postLoad
,而使用Android Room,您可以使用LiveData
字段。)然后您根本不需要在表中存储字段
关于这一问题的进一步解读:
public class Order {
private int quantity;
private long price;
private long totalPrice;
public int getQuantity() { return quantity; }
public void setQuantity(int newQuantity) {
quantity = newQuantity;
updateTotalPrice();
}
public long getPrice() { return price; }
public void setPrice(long newPrice) {
price = newPrice;
updateTotalPrice();
}
private void updateTotalPrice() {
totalPrice = quantity * price;
}
public long getTotalPrice() { return totalPrice; }
}