松散耦合的例子

时间:2010-11-27 12:27:19

标签: loose-coupling

介绍代码:

public interface Course {

    /**
     * returns the number of units (hours) a specific course is
     */
    public int units();

    /**
     * returns the number of students signed up for the course
     */
    public int numOfStudents();

    /**
     * returns the maximum number of students the course can have signed up to it
     */
    public int maxNumStudents();

    /**
     * returns whether or not the student is enrolled in the course
     */
    public boolean registered(Student s);

    /**
     * enrolls s in the course
     * 
     * @pre     this.registered(s) == false
     * @pre     this.numOfStudents() < this.maxNumStudents()
     * 
     * @post    this.registered(s) == true
     * @post    this.numOfStudents() == $prev(this.numOfStudents()) + 1
     */
    public void register(Student s);

}


public interface Student {

    /**
     * enrolls the student in course c
     * 
     * @pre     c.registered(this) == false
     * @pre     c.numOfStudents() < c.maxNumStudents()
     * @pre     this.totalUnits() + c.units() <= 10
     * 
     * @post    c.registered(s) == true
     * @post    this.totalUnits() == $prev(this.totalUnits()) + c.units()
     */
    public void register(Course c);

    /**
     * return the total number of units this student currently is enrolled in
     * 
     * @pre     true
     * @post    0 <= $ret <= 10
     */
    public int totalUnits();

}

在示例代码中我试图描述两个独立的实体(接口/类/无论什么),一方面应该(我想,至少)松散耦合但另一方面确实依赖于彼此并且需要彼此有一定的了解。

在上面的场景中,我需要一个第三类,实际上将它们组合成一个工作系统。它很难看,因为截至目前,上面的定义与松散耦合一样 - student.register(c)只更改学生对象,而course.register只更改课程对象。因此,统一类必须同时运行s.register(c)和c.register(s)。

虽然如果我将所有register()逻辑重新连接到一个类,那么我紧紧耦合它们。

有更简洁的设计方法吗?

1 个答案:

答案 0 :(得分:4)

通过使用接口,您已经降低了具体对象之间的依赖关系,这是一件好事。您的系统需要一些依赖关系,因此您必须决定您想要容忍多少。

考虑系统中的学生可以注册课程。由于课程是一个界面,因此可以实施许多不同类型的课程,然后学生就可以注册其中任何一门课程。只要学生只知道应该没问题的课程界面。对于课程来说同样的事情,它只知道学生界面而不是具体的学生。

只有一件事。在你描述的双向关联的情况下,我喜欢让一方成为关系的所有者。也就是说,我可以决定学生拥有这种关系,因此,学生可以注册课程,但课程不会注册学生。

然后所有客户端代码将进行一次调用s.register(c)。然后,学生中的注册将处理关系的反面。这减少了客户端代码知道关系双方的需要。