An application of Demeter's rule in design pattern programming of Java

  • 2020-05-05 11:14:56
  • OfStack

Definition: an object should know at least

about other objects

The core concept of Demeter's law is class decoupling, weak coupling. Only after weak coupling, class reusability can be improved.

Prison inmates are not supposed to interact with people outside the prison, although there may be family visits. The prison is the class, the inmate is the information inside the class, and the prison guard is the equivalent of the enforcement of Demeter's law

Demeter's law states:
(1) in the class division, should create a weak coupling of the class;

(2) in the structural design of the class, each class should reduce the access rights of its members as far as possible;

(3) in class design, whenever possible, a class should be designed as an invariant class;

(4) on the reference to other classes, the reference of one object to other objects should be minimized;

(5) reduce the access rights of the class as far as possible;

(6) use serialization cautiously;

(7) instead of exposing class members, provide accessors (properties).

For example, there is a group company with subsidiaries and direct departments, which now requires the printing out of ID of employees of all subsidiaries. So let's look at the design that violates Demeter's rule.


// Head office staff  
class Employee{ 
  private String id; 
  public void setId(String id){ 
    this.id = id; 
  } 
  public String getId(){ 
    return id; 
  } 
} 
 
// Branch staff  
class SubEmployee{ 
  private String id; 
  public void setId(String id){ 
    this.id = id; 
  } 
  public String getId(){ 
    return id; 
  } 
} 
 
class SubCompanyManager{ 
  public List<SubEmployee> getAllEmployee(){ 
    List<SubEmployee> list = new ArrayList<SubEmployee>(); 
    for(int i=0; i<100; i++){ 
      SubEmployee emp = new SubEmployee(); 
      // Assign one person to the branch in order ID 
      emp.setId(" branch "+i); 
      list.add(emp); 
    } 
    return list; 
  } 
} 
 
class CompanyManager{ 
 
  public List<Employee> getAllEmployee(){ 
    List<Employee> list = new ArrayList<Employee>(); 
    for(int i=0; i<30; i++){ 
      Employee emp = new Employee(); 
      // Assign one head office person in order ID 
      emp.setId(" The head office "+i); 
      list.add(emp); 
    } 
    return list; 
  } 
   
  public void printAllEmployee(SubCompanyManager sub){ 
    List<SubEmployee> list1 = sub.getAllEmployee(); 
    for(SubEmployee e:list1){ 
      System.out.println(e.getId()); 
    } 
 
    List<Employee> list2 = this.getAllEmployee(); 
    for(Employee e:list2){ 
      System.out.println(e.getId()); 
    } 
  } 
} 
 
public class Client{ 
  public static void main(String[] args){ 
    CompanyManager e = new CompanyManager(); 
    e.printAllEmployee(new SubCompanyManager()); 
  } 
} 

              in CompanyManager now the main problem in this design, according to the law of Demeter, only with direct friends communication occurs, and SubEmployee not CompanyManager class direct friends (coupling, in the local variables do not belong to the direct friends), logically corporation only branch of the coupling line with him, don't have any contact with an employee of the branch, this design is obviously increased the unnecessary coupling. According to Demeter's rule, such indirect friend coupling in a class should be avoided. The modified code is as follows :


class SubCompanyManager{ 
  public List<SubEmployee> getAllEmployee(){ 
    List<SubEmployee> list = new ArrayList<SubEmployee>(); 
    for(int i=0; i<100; i++){ 
      SubEmployee emp = new SubEmployee(); 
      // Assign one person to the branch in order ID 
      emp.setId(" branch "+i); 
      list.add(emp); 
    } 
    return list; 
  } 
  public void printEmployee(){ 
    List<SubEmployee> list = this.getAllEmployee(); 
    for(SubEmployee e:list){ 
      System.out.println(e.getId()); 
    } 
  } 
} 
 
class CompanyManager{ 
  public List<Employee> getAllEmployee(){ 
    List<Employee> list = new ArrayList<Employee>(); 
    for(int i=0; i<30; i++){ 
      Employee emp = new Employee(); 
      // Assign one head office person in order ID 
      emp.setId(" The head office "+i); 
      list.add(emp); 
    } 
    return list; 
  } 
   
  public void printAllEmployee(SubCompanyManager sub){ 
    sub.printEmployee(); 
    List<Employee> list2 = this.getAllEmployee(); 
    for(Employee e:list2){ 
      System.out.println(e.getId()); 
    } 
  } 
} 

After modification,               added the method of printer ID to the branch office, which was directly called by the head office to print, thus avoiding coupling with the branch office employees.
The original intention of the Demeter's rule is to reduce coupling between classes, and since each class reduces unnecessary dependencies, coupling can indeed be reduced. However, everything has its own degree. Although communication with indirect classes can be avoided, communication is bound to take place through an "intermediary". For example, in this case, the head office makes contact with employees of the branch company through the "intermediary" of the branch company. Excessive use of the Demeter principle will result in a large number of such mediation and delivery classes, resulting in greater system complexity. Therefore, when applying Demeter's rule, we have to balance repeatedly, to achieve both clear structure and high cohesion and low coupling.


Related articles: