【发布时间】:2017-10-18 07:43:17
【问题描述】:
假设我有一个班级Order。一个Order 可以通过调用Order.finish() 方法来完成。在内部,当 Order 完成时,会设置完成日期:
Order.java
public void finish() {
finishingDate = new Date();
}
在应用的业务逻辑中,不需要暴露Order的finishingDate,所以它是一个没有getter的私有字段。
想象一下,在完成Order 之后,我想在数据库中更新它。例如,我可以有一个带有 update 方法的 DAO:
OrderDao.java
public void update(Order order) {
//UPDATE FROM ORDERS SET ...
}
在该方法中,我需要Order 的内部状态,以更新表字段。但是我之前说过,我的业务逻辑中不需要暴露Order的finishingDate字段。
如果我添加一个Order.getFinishingDate() 方法:
- 我正在更改
Order类的合同而不增加业务价值,ubt 出于“技术”原因(数据库中的UPDATE) - 我违反了面向对象编程的封装原则,因为我暴露了内部状态。
你如何解决这个问题?您认为添加 getter(如 ORM 中的“实体”类)是可以接受的吗?
我看到了一种不同的方法,其中类本身(实现)甚至知道如何保持自身。像这样的东西(非常幼稚的例子,只是为了问题):
public interface Order {
void finish();
boolean isFinished();
}
public class DbOrder implements Order {
private final int id;
private final Database db;
//ctor. An implementation of Database is injected
@Override
public void finish() {
db.update("ORDERS", "FINISHING_DATE", new Date(), "ID=" + id);
}
@Override
public boolean isFinished() {
Date finishingDate = db.select("ORDERS", "FINISHING_DATE", "ID=" + id);
return finishingDate != null;
}
}
public interface Database {
void update(String table, String columnName, Object newValue, String whereClause);
void select(String table, String columnName, String whereClause);
}
除了性能问题(实际上,它可以被缓存或其他),我喜欢这种方法,但它迫使我们在测试时模拟很多东西,因为所有逻辑都不是“内存中的”。我的意思是,“执行”被测逻辑所需的数据不仅仅是内存中的一个字段,而是由外部组件提供的:在这种情况下,Database。
【问题讨论】:
标签: oop