본문 바로가기
독서에서 한걸음

Large Class

by oncerun 2022. 12. 26.
반응형

 

어떤 클래스가 너무 많은 일을 하다 보면 필드도 많아지고 중복 코드도 보이기 시작한다.

 

클라이언트가 해당 클래스가 제공하는 기능 중에 일부만 사용한다면 각각의 세부기능을 별도의 클래스로 분리할 수 있다.

 

필드들이 모이다보면 결국 필드를 사용하는 기능들이 점점 모아지고 나중에 떼어내기가 매우 힘들어진다.

 

이 경우 관련있는 필드를 클래스 추출하기를 통해 한 곳으로 모을 수 있다.

 

만약 상속 구조를 만들 수 있다면 슈퍼 클래스 추출하기 또는 타입 코드를 서브클래스로 교체하기를 적용할 수 있다.

 

이 중 슈퍼클래스를 추출하기를 해보자.

 

 

Extract Superclass

 

 

두 개의 클래스에서 비슷한 것들이 보인다면 상속을 적용하고 슈퍼클래스로 필드 올리기와 메서드 올리기를 사용한다. 

 

대안으로는 클래스 추출하기를 적용해 위임을 사용할 수 있다. 

 

간단히 상속을 적용한 이후, 나중에 필요하다면 슈퍼클래스를 위임으로 교체하기를 적용해도 된다.

 


public class Department {

    private String name;

    private List<Employee> staff;

    public String getName() {
        return name;
    }

    public List<Employee> getStaff() {
        return staff;
    }

    public double totalMonthlyCost() {
        return this.staff.stream().mapToDouble(e -> e.getMonthlyCost()).sum();
    }

    public double totalAnnualCost() {
        return this.totalMonthlyCost() * 12;
    }

    public int headCount() {
        return this.staff.size();
    }
}
public class Employee {

    private Integer id;

    private String name;

    private double monthlyCost;

    public double annualCost() {
        return this.monthlyCost * 12;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public double getMonthlyCost() {
        return monthlyCost;
    }
}

 

매년 지원되는 금액과 name 필드를 슈퍼클래스를 만들어보자.

 

이를 위해 함수명을 일치 시켜주는 작업이 필요하다.

 

monthlyCost를 사용하는 메서드를  monthlyCost() 메서드 이름으로 통일한 이후 슈퍼 클래스에서 추상메서드로 변경해 주자.  monthlyCost()를 추상 메소드로 변경한다. 

 

annualCost 내부 구현도 같이 때문에 슈퍼클래스로 올려줄 수 있다.

 

또한 name의 값은 다르지만 동일하게 사용됨으로 필드를 올려줄 수 있다. 이를 적용한 슈퍼클래스는 다음과 같다.

 

public abstract class Party {

    protected String name;

    public Party(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public double annualCost() {
        return this.monthlyCost() * 12;
    }

    public abstract double monthlyCost();
}

 

부모가 생겼기 때문에 자식에서는 부모 생성자를 호출하도록 고쳐주고 부모의 메서드를 사용하는 경우 메서드를 제거해주고 추상 메서드를 오버라이드 하자.

 

public class Department extends Party{

    private List<Employee> staff;

    public Department(String name) {
        super(name);
    }

    public List<Employee> getStaff() {
        return staff;
    }

    @Override
    public double monthlyCost() {
        return this.staff.stream().mapToDouble(Employee::monthlyCost).sum();
    }

    public int headCount() {
        return this.staff.size();
    }
}
public class Employee extends Party{

    private Integer id;

    private double monthlyCost;

    public Employee(String name) {
        super(name);
    }

    public Integer getId() {
        return id;
    }
    @Override
    public double monthlyCost() {
        return monthlyCost;
    }
}
반응형

'독서에서 한걸음' 카테고리의 다른 글

Refused Bequest  (0) 2022.12.28
Alternative Classes with Different Interfaces  (0) 2022.12.27
Insider Trading  (0) 2022.12.26
Middle Man  (0) 2022.12.24
Message Chains  (0) 2022.12.24

댓글