Java의 디자인 모드 프로그래밍에서 디미트 법칙의 응용 예시
디미트 법칙의 핵심 관념은 바로 클래스 간의 결합, 약한 결합이다. 약한 결합이 이루어진 후에야 클래스의 복용성이 높아질 수 있다.
이미지의 비유는 교도소 안의 범인은 바깥사람과 접촉해서는 안 되고 당연히 친척 방문이 있을지도 모른다는 것과 유사하다.이곳의 감옥은 클래스이고, 안의 범인은 클래스 내부의 정보이며, 감옥 안의 교도관은 디미트 법칙의 집행자에 해당한다
디미트의 법칙은 다음과 같이 주장한다.
(1) 클래스의 구분에 있어 약한 결합이 있는 클래스를 만들어야 한다.
(2) 클래스의 구조 설계에 있어 모든 클래스는 구성원의 접근 권한을 최대한 낮춰야 한다.
(3) 클래스의 디자인에 있어 가능하다면 하나의 클래스는 불변류로 설계해야 한다.
(4) 다른 종류의 인용에 있어서 한 대상이 다른 대상에 대한 인용은 최저로 내려야 한다.
(5) 클래스의 접근 권한을 최대한 낮춘다.
(6) 서열화 기능을 신중하게 사용한다.
(7) 클래스 구성원을 노출하지 말고 해당하는 접근기(속성)를 제공해야 한다.
예를 들어 하나의 그룹이 있는데 산하에 지사와 직속 부서가 있는데 현재 모든 부하 부서의 직원 ID를 인쇄할 것을 요구한다.먼저 디미트의 법칙에 어긋나는 디자인을 살펴보자.
//
class Employee{
private String id;
public void setId(String id){
this.id = id;
}
public String getId(){
return id;
}
}
//
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();
// ID
emp.setId(" "+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();
// ID
emp.setId(" "+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());
}
}
현재 이 디자인의 주요 문제는 Company Manager에서 디미트 법칙에 따라 직접적인 친구와 통신만 하고 SubEmployee 클래스는 Company Manager 클래스의 직접적인 친구가 아니다(국부적 변수로 나타난 결합은 직접적인 친구에 속하지 않는다). 논리적으로 본사는 그의 지사와 결합만 하면 되고 지사의 직원과 아무런 관계가 없다.이런 설계는 분명히 불필요한 결합을 증가시켰다.디미트의 법칙에 따르면 클래스에 이런 비직접적인 친구 관계의 결합이 나타나는 것을 피해야 한다.수정된 코드는 다음과 같습니다.
class SubCompanyManager{
public List<SubEmployee> getAllEmployee(){
List<SubEmployee> list = new ArrayList<SubEmployee>();
for(int i=0; i<100; i++){
SubEmployee emp = new SubEmployee();
// ID
emp.setId(" "+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();
// ID
emp.setId(" "+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());
}
}
}
수정 후 지사에 인쇄 인원 ID를 추가하는 방법을 본사가 직접 호출하여 인쇄함으로써 지사 직원과의 결합을 피했다.디미트 법칙의 초지는 클래스 간의 결합을 낮추는 것이다. 모든 클래스가 불필요한 의존을 줄였기 때문에 확실히 결합 관계를 낮출 수 있다.그러나 매사에 한도가 있기 때문에 비직접적인 유형과의 통신을 피할 수 있지만 통신을 하려면 반드시 하나의'중개'를 통해 연락이 발생한다. 예를 들어 본 예에서 본사는 지사라는'중개'를 통해 지사의 직원과 연락이 발생한다.디미트 원칙을 지나치게 사용하면 이런 중개와 전달 유형이 대량으로 생겨나 시스템의 복잡도가 커진다.그래서 디미트의 법칙을 채택할 때 반복적으로 따져야 한다. 구조가 뚜렷할 뿐만 아니라 고내중합과 저결합도 해야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.