我正在努力想出一个在OO模型中添加双向关系的好方法。假设有一个客户可以下多个订单,也就是说客户和订单类之间存在一对多关联,需要在两个方向上遍历:对于特定客户,应该可以告诉所有订单他们已下订单,对于订单,应该可以告诉客户。
这是一段Java代码,尽管这个问题主要与语言无关:
class Customer {
private Set orders = new HashSet<Order> ();
public void placeOrder (Order o) {
orders.add(o);
o.setCustomer(this);
}
}
class Order {
private Customer customer;
public void setCustomer (Customer c) {
customer = c;
}
}
让我感到不安的是,鉴于模特有人可以轻易打电话:
o.setCustomer(c);
而不是正确的
c.placeOrder(o);
形成单向链路而不是双向链路。
仍在学习OOP,任何人都可以请求帮助解决这个问题的惯用和实用方法,而不需要求助于“反思”或花哨的框架(无论如何都要依靠反思)。
P.S。有一个类似的问题:Managing bidirectional associations in my java model,但我觉得它不能回答我的请求。
P.S.S。任何在db4o之上实现业务模型的现实项目源代码的链接都非常感谢!
答案 0 :(得分:5)
首先,除非您计划在客户之间移动订单,否则我认为您不应该提供setCustomer()
方法,客户应该是构造函数的参数并保持不变。
然后,用户不应该访问构造函数,只使用Owner
的工厂方法。
答案 1 :(得分:0)
没有一个答案。这真的取决于所涉及的课程。在你的情况下,你显然不想让人们选择做无效的事情,所以我会摆脱Order.SetCustomer。
但情况并非总是如此。就像我说的那样,这取决于所涉及的课程。
答案 2 :(得分:0)
如果您在Customer.placeOrder(Order)
中维持双向关系,为什么不在Order.setCustomer(Customer)
中执行相同的操作?
class Order {
private Customer customer;
public void setCustomer (Customer c) {
customer = c;
c.getOrders().add(this);
// ... or Customer.placeOrder(this)
}
}
它似乎是复制代码,但它解决了问题。但更简单的做法是尽可能避免双向关系。
答案 3 :(得分:0)
我认为在这种情况下,最好的方法是将布线的职责委托给另一个类:
class OrderManager {
void placeOrder(Customer c, Order o){
c.addOrder(o);
o.setCustomer(c);
}
}
class Customer {
private Set<Order> orders = new LinkedHashSet<Order>();
void addOrder(Order o){ orders.add(o); }
}
class Order {
private Customer customer;
void setCustomer(Customer c){ this.customer=c; }
}