Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java对象字段值取决于其他字段-最佳实践模式?_Java_Oop - Fatal编程技术网

Java对象字段值取决于其他字段-最佳实践模式?

Java对象字段值取决于其他字段-最佳实践模式?,java,oop,Java,Oop,我有一个简单的java对象 public class Order { private int quantity; private long price; private long totalPrice; } 我将只存储数量和价格,totalPrice字段将根据数量*价格生成 现在我在Order类中有了名为populateTotalPrice()的方法。但我似乎把一个逻辑放在一个实体类中,它可能是一个反模式 我的另一个选择是使用helper静态方法 这种行为的最佳实践是什么?是的

我有一个简单的java对象

 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
字段。)然后您根本不需要在表中存储字段

关于这一问题的进一步解读:


我需要存储总价,以便根据totalPrice@user1955934“存储”和“查询”是什么意思?
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; }
}