介绍代码:
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()逻辑重新连接到一个类,那么我紧紧耦合它们。
有更简洁的设计方法吗?
答案 0 :(得分:4)
通过使用接口,您已经降低了具体对象之间的依赖关系,这是一件好事。您的系统需要一些依赖关系,因此您必须决定您想要容忍多少。
考虑系统中的学生可以注册课程。由于课程是一个界面,因此可以实施许多不同类型的课程,然后学生就可以注册其中任何一门课程。只要学生只知道应该没问题的课程界面。对于课程来说同样的事情,它只知道学生界面而不是具体的学生。
只有一件事。在你描述的双向关联的情况下,我喜欢让一方成为关系的所有者。也就是说,我可以决定学生拥有这种关系,因此,学生可以注册课程,但课程不会注册学生。
然后所有客户端代码将进行一次调用s.register(c)。然后,学生中的注册将处理关系的反面。这减少了客户端代码知道关系双方的需要。