以下代码打破了Law of Demeter:
public class Student extends Person {
private Grades grades;
public Student() {
}
/** Must never return null; throw an appropriately named exception, instead. */
private synchronized Grades getGrades() throws GradesException {
if( this.grades == null ) {
this.grades = createGrades();
}
return this.grades;
}
/** Create a new instance of grades for this student. */
protected Grades createGrades() throws GradesException {
// Reads the grades from the database, if needed.
//
return new Grades();
}
/** Answers if this student was graded by a teacher with the given name. */
public boolean isTeacher( int year, String name ) throws GradesException, TeacherException {
// The method only knows about Teacher instances.
//
return getTeacher( year ).nameEquals( name );
}
private Grades getGradesForYear( int year ) throws GradesException {
// The method only knows about Grades instances.
//
return getGrades().getForYear( year );
}
private Teacher getTeacher( int year ) throws GradesException, TeacherException {
// This method knows about Grades and Teacher instances. A mistake?
//
return getGradesForYear( year ).getTeacher();
}
}
public class Teacher extends Person {
public Teacher() {
}
/**
* This method will take into consideration first name,
* last name, middle initial, case sensitivity, and
* eventually it could answer true to wild cards and
* regular expressions.
*/
public boolean nameEquals( String name ) {
return getName().equalsIgnoreCase( name );
}
/** Never returns null. */
private synchronized String getName() {
if( this.name == null ) {
this.name == "";
}
return this.name;
}
}
问题
答案 0 :(得分:3)
我认为这是两个问题:
Grades
逻辑与Student
混合得太多了。它应该在Grades
class Teacher
的逻辑被放入Student
。结论:学生对教师和成绩的内部结构和逻辑了解太多,并且会破坏LoD
答案 1 :(得分:2)
这样的大多数问题都可以通过重新访问您的域模型来解决。
看起来学生的责任要大于应有的责任。它只应该有一个改变的理由。
我会通过添加一个ReportCard对象来重构它。
public class ReportCard
{
public Student Student...
public int Year...
public ReportCardItem[] ReportCardItems...
getGrades()...
createGrades()...
}
public class ReportCardItem
{
public Grade Grade...
public string Subject...
public Teacher Teacher...
}
答案 2 :(得分:1)
Person.isTeacher
根据你提到的维基百科文章“到达”。
我很惊讶地发现学生的成绩列表。这不应该是学校知道和管理的吗?我问学校,哪位老师在哪一年给学生评分......
答案 3 :(得分:1)
违反德米特定律的类Student中的方法
private Grades getGradesForYear( int year )
private Teacher getTeacher( int year )
因为这些将域对象Grades和Teacher暴露给应用程序。
假设您希望继续隐藏成绩中学生和教师的成绩,解决此问题的一种方法是在类学生中定义代理方法(也称为委托方法),对内部成绩和教师进行操作代表应用程序的对象,类似于方法Student.isTeacher(int, String)
。这个解决方案可能导致学生成绩和教师方法的重复,这是一个尊重LofD的disadvantage课程设计。
更好的解决方案是从学生中删除成绩和教师,并将他们全部放在另一个班级,比如成绩单:
class Transcript {
Student student;
Teacher teacher;
Grades grades;
Integer year;
}
答案 4 :(得分:0)
让这两个私有函数破坏了LoD。
private Grades getGradesForYear( int year )
private Teacher getTeacher( int year )
学生不需要逻辑来执行此类任务。
我重新设计的方法是将数据与逻辑分开。学生应该纯粹只是一个数据。它应该包含有关学生和学生的信息。因此,这不包括成绩,因为该概念需要其他人,如主题和教师。
老师也一样。然后我会创建一个存储成绩信息的地方和另一个主题信息的地方。
要执行类似的任务,我会这样做:
gradesDatabase.getGrade(subject, student);
subjectDatabase.getTeacher(subject, student);
主题也是数据对象。