11장. 일반화 다루기
일반화(generalization)은 하나의 리팩토링 군을 만드는데, 주로 상속 구조에서 메소드를 옮기는 것을 다룬다.
Pull Up Field
- 두 서브클래스가 동일한 필드를 가지고 있다면, 그 필드를 수퍼클래스로 옮겨라.

동기
- 중복된 데이터 정의를 없애고, 그 필드를 사용하는 동작을 서브클래스에서 수퍼클래스로 옮긴다.
Pull Up Method
- 동일한 일을 하는 메소드를 여러 서브클래스에서 가지고 있다면, 이 메소드를 수퍼클래스로 옮겨라.

동기
- 중복된 동작을 제거한다.
- 적용하기 가장 쉬운 경우는 같은 몸체를 가지고 있을 때이다. (이는 copy and paste를 한 경우다)
- 성가신 경우는 메소드 몸체는 서브클래스에 있지만 수퍼클래스에는 없는 메소드나 변수를 참조하고 있을 경우다
이런 경우는 슈퍼 클래스에 추상 메소드로 만들 수 있다. - 비슷하지만 동일하지 않은 두 메소드가 있다면 Form Template Method를 사용 할 수도 있다.
Pull Up Constructor Body
- 서브클래스들이 대부분 동일한 몸체를 가진 생성자를 가지고 있다면 수퍼클래스에 생성자를 만들고, 서브클래스 메소드에서 이것을 호출하라.
{code} class Manager extends Employee... public Manager (String name, String id, int grade) { _name = name; _id = id; _grade = grade; } {code} | → | {code} public Manager (String name, String id, int grade) { super (name, id); _grade = grade; } {code} |
동기
- 서브 클래스의 생성자에서는 공통된 동작이 있으면 수퍼클래스의 생성자를 만들고 서브클래스 메소드에서 호출하라.
- 예제소스에서는 id, name을 수퍼클래스에서 정의 하였다.
Push Down Method
- 수퍼클래스에 있는 동작이 서브클래스 중 일부에만 관련되어 있다면, 그 동작을 관련된 서브클래스로 옮겨라.

동기
- Push Down Method는 Pull Up Method의 반대다.
- 수퍼클래스의 동작이 특정한 서브클래스에서만 사용될 때 사용한다.
Push Down Field
- 어떤 필드가 일부 서브클래스에 의해서만 사용되고 있다면, 그 필드를 관련된 서브클래스로 옮겨라.

동기
- Push Down Field는 Pull Up Field의 반대다.
- 어떤 필드를 수퍼클래스에서는 필요로 하지 않지만 서브클래스에서는 필요로 할때 사용한다.
- 어떤 클래스가 일부 인스턴스에 의해서만 사용되는 기능을 가지고 있다면, 기능의 부분집합을 담당하는 서브클래스를 만들어라.

동기
- 어떤 클래스가 그 클래스의 모든 인스턴스가 아닌 일부 인스턴스에 의해서만 사용되는 기능을 가지고 있을때 사용한다.
- 일부 동작과 데이터가 단지 어떤 경우에만 필요한 경우
- 책 예제는 JobItem에서 LaborItem 서브 클래스를 생성하고 JobItem을 상속한다.
- 비슷한 메소드와 필드를 가진 두개의 클래스가 있다면, 수퍼클래스를 만들어서 공통된 메소드와 필드를 수퍼클래스로 옮겨라.

동기
- 중복된 코드는 시스템에 있어서 가장 나쁜것 가운데 하나이다.
- 중복된 코드의 한 형태, 동일한 방법 또는 서로 다른 방법으로 비슷한 일을 하는 두개의 클래스가 존재하면
객체는 상속을 통해 이런 상황을 단순화하는 고유의 메커니즘을 제공한다. - subclass Department, Employee의 getTotalAnnualCost, getAnnualCost , getName 메소드를
superclass Party의 getAnnualCost, getName 메소드로 move
- 여러 클라이언트가 한 클래스의 인터페이스의 동일한 부분 집합을 사용하고 있거나, 두 클래스가 공통된 인터페이스를 가지는 부분이 있다면,
그 부분 집합을 인터페이스로 뽑아내라.

동기
- 한글 해석이 더 어렵네 책 390, 391 예제 참고
- 어떤 클래스를 사용한다는 것은 종종 그 클래스가 맡고 있는 책임 영역을 모두 사용한다는 것을 의미한다.
책임진 부분 집합을 독립시켜 시스템에서 사용할 때 좀 더 명확하게 하는 것이 좋은데, 클래스가 서로 다른 상황에서 별개의 역할을 가지고 있을 때는
언제나 인터페이스를 사용하는 것이 좋다. - 한 클래스의 밖으로 나가는(outbound) 인터페이스, 즉 그 클래스가 서버에 하는 오퍼레이션 같은 것을 기술하고 싶은 경우 사용하고, 다른 종류의 서버를
허용하고 싶으면, 단지 인터페이스를 구현하면 된다.
Collapse Hierarchy
- 수퍼클래스와 서브클래스가 별로 다르지 않다면, 그것들을 하나로 합쳐라.

동기
- 얽혀버린 구조를 정라하다보면 더 이상 어떠한 가치도 도하지 못하는 서브클래스를 발견할지도 모르는데 이런 경우에는 클래스를 합친다.
- 각각의 서브 클래스에 동일한 순서로 비슷한 단계를 행하지만 단계가 완전히 같지는 않은 두 메소드가 있다면,
그 단계를 동일한 시그니처를 가진 메소드로 만들어라. 이렇게 하면 원래의 두 메소드는 서로 같아지므로 수퍼클래스로 올릴 수 있다.

동기
- 두 메소드가 대체로 비슷하게 보이는 단계를 같은 순서로 진행하지만 각각의 단계는 동일하지 않은 경우이다.
- 이런 경우 순서는 수퍼클래스로 옮기고, 다형성을 사용해서 각각의 단계가 자신의 일을 다른 방법으로 처리하도록 할 수 있다.
- page 394 예제는 Strategy 패턴을 사용하여 구현하였다.
Replace Inheritance with Delegation
- 서브클래스가 수퍼클래스 인터페이스의 일부분만 사용하거나 또는 데이터를 상속 받고 싶지 않은 경우
수퍼클래스를 위한 필드를 만들고 메소드들이 수퍼클래스에 위임하도록 변경한 후 상속 관계를 제거한다.

동기
- 수퍼클래스에 있는 오퍼레이션의 상당 부분이 서브클래스에서는 별로 적절하지 않다는 것을 알았을때
위임을 사용하여 위임되는 클래스의 단지 일부분만 사용하고 있다는 것을 명확하게 한다. - 책 402page 예제
Replace Delegation with Inheritance
- 위임을 사용하고 있는데 전체 인터페이스에 대해 간단한 위임을 자주 작성하고 있다면, 위임하는 클래스를 대리객체의 서브클래스로 만들어라.

동기
- Replace Inheritance with Delegation 의 반대 개념이다.
- 대리객체의 모든 메소드를 사용하고 있으면 매우 쉽게 상속을 사용하도록 바꿀 수 있다.
- 책 405page 예제
문서에 대하여