在OO模型中添加双向关系的最佳实践

时间:2010-10-20 22:18:21

标签: java language-agnostic oop model db4o

我正在努力想出一个在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之上实现业务模型的现实项目源代码的链接都非常感谢!

4 个答案:

答案 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; }
}