最少知道原則

Prerequisites:

迪米特原則

英文是Law of Demeter

迪米特原則也就是最少知道原則。

什麼是最少知道原則?假設A類別用到B類別的方法,A類別不會想知道B類別的內部結構以及程式是如何寫的,B類別只要提供一個public的方法給A類呼叫就好。

朋友關係

A類別用到B類別,所謂的「用到」,可能是依賴、聚合、組合、關連的關係,以下都是朋友關係。

  • 方法參數(依賴)
  • setter(聚合)
  • 成員變數(組合或關聯)
  • 傳回值

區域變數就不是朋友關係。

根據最少知道原則,類別與類別之間的關係,一定要是朋友關係。

朋友關係範例

Student類別

1
2
3
4
5
6
7
class Student {
  String name;
  Student() {}
  Student(String name) {
    this.name = name;
  }
}

對於getAllStudent()方法中,傳回值類型有Student,所以Student是朋友。

1
2
3
4
5
6
7
8
9
10
class StudentManager {
  List<Student> getAllStudent() {
    List<Student> list = new ArrayList<>();
    for (int i = 0; i < 10 ; i++) {
      Student student = new Student("student" + i);
      list.add(student);
    }
    return list;
  }
}

不是朋友範例

參數StudentManager是printAll()方法的朋友

1
2
3
4
5
6
7
8
class PrintManager {
  void printAll(StudentManager studentManager) {
    List<Student> students = studentManager.getAllStudent();
    for (int i = 0; i < students.size(); i++) {
      System.out.println(students.get(i).name);
    }
  }
}

但是區域變數List,Student既不是方法參數也不是傳回值類型,所以Student不是朋友。

1
List<Student> students = studentManager.getAllStudent();

如何修正?

先前有提到「A類別用到B類別的方法,A類別不會想知道B類別的內部結構以及程式是如何寫的,B類別只要提供一個public的方法給A類呼叫就好。」

但是PrintManager.printAll(),居然取出studentManager中的學生清單,違反「不會知道其它類別的內部結構」。

把印出學生姓名的程式碼,放回StudentManager,提供一個public的printAllStudent()方法給別人呼叫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class StudentManager {
  List<Student> getAllStudent() {
    List<Student> list = new ArrayList<>();
    for (int i = 0; i < 10 ; i++) {
      Student student = new Student("student" + i);
      list.add(student);
    }
    return list;
  }

  // 印出學生
  void printAllStudent() {
    List<Student> students = this.getAllStudent();
    for (int i = 0; i < students.size(); i++) {
      System.out.println(students.get(i).name);
    }
  }
}

PrintManager修改成,透過朋友,也就是參數studentManager,去印出學生

1
2
3
4
5
class PrintManager {
  void printAll(StudentManager studentManager) {
    studentManager.printAllStudent();
  }
}

results matching ""

    No results matching ""