* 상속을 위임으로 치환 리팩토링 ( Replace Inheritance With Delegation )
* 상속
- 상위 클래스에서 선언한 필드와 메서드를 하위 클래스에서 이용할 수 있음.
이를 부모가 자식에게 물려주는(inherit)것에 비유해서 상속(inheritance)이라고 부름.
많은 객체지향 프로그램에서 상속 기능이 있음.
* 위임
- 다른 인스턴스의 메서드를 호출해서 처리하는것을 처리를 위임한다(delegate)라고 표현.
- 위임(delegation)이란 '맡긴다'는 의미임.
* 상속과 위임의 비교
- 상속은 클래스 사이의 관계이고, 위임은 인스턴스 사이의 관계, 이는 상위 클래스에서 상속받을 메서드나 필드는 인스턴스마다 정할 순 없지만,
작업을 위탁할 곳은 인스턴스마다 정할 수 있음
- 상속은 정적인 관계이고, 위임은 동적인 관계임. 이는 상속 관계는 컴파일할 때 정해지고 실행 중에 변경할 수 없지만, 위임 관계는 실행 중에 변경할 수 없기 때문임.
* 상속을 위임으로 치환
- 객체 지향 프로그래밍을 배우다 보면 상속을 남용하기도 함. 상속을 사용하면 조금만 코딩해도 상위 클래스의 기능을 바로 사용할 수 있기 때문.
- 하지만 상속을 사용해야 할 곳이 아닌 곳까지 상속을 사용하면 프로그램이 더러워지고 재사용하기 어려워짐.
- 상속을 위임으로 치환(Replace Inheritance with Delegation) 리팩토링은 부적절한 상속을 위임으로 치환함. 이렇게 하면 클래스의 역할이 명확해지고 재사용도 쉬워짐.
* 리팩토링 전 코드
package ReplaceInheritanceWithDelegation.before;
import java.util.Random;
public class Dice extends Random {
/**
*
*/
private static final long serialVersionUID = 1L;
public Dice() {
super(314159L);
}
public Dice(long seed) {
super(seed);
}
@Override public int nextInt() {
return nextInt(6) + 1;
}
@Override public void nextBytes(byte[] bytes) {
throw new UnsupportedOperationException();
}
@Override public long nextLong() {
throw new UnsupportedOperationException();
}
@Override public boolean nextBoolean() {
throw new UnsupportedOperationException();
}
@Override public float nextFloat() {
throw new UnsupportedOperationException();
}
@Override public double nextDouble() {
throw new UnsupportedOperationException();
}
@Override public double nextGaussian() {
throw new UnsupportedOperationException();
}
}
package ReplaceInheritanceWithDelegation.before;
public class Main {
public static void main(String[] args) {
Dice dice0 = new Dice();
Dice dice1 = new Dice(456L);
Dice dice2 = new Dice();
Dice[] dices = {
dice0,
dice1,
dice2,
};
dice2.setSeed(456L);
for(Dice d : dices) {
for(int i=0; i< 10; i++) {
System.out.printf("%d, ", d.nextInt());
}
System.out.println();
}
}
}
* 리팩토링 후 코드
package ReplaceInheritanceWithDelegation.before;
import java.util.Random;
public class Dice {
private final Random _random;
public Dice() {
_random = new Random(314159L);
}
public Dice(long seed) {
_random = new Random(seed);
}
public int nextInt() {
return _random.nextInt(6)+1;
}
public void setSeed(long seed) {
_random.setSeed(seed);
}
}
관측 데이터 복제 리팩토링 (0) | 2020.02.13 |
---|---|
생성자를 팩토리 메서드로 치환 (Replace Constructor with Factory Method ) (0) | 2020.02.10 |
에러 코드를 예외로 전환( Replace Error Code with Exception ) (0) | 2020.02.09 |
분류 코드를 상태/전략 패턴으로 치환 (0) | 2020.02.08 |
분류 코드를 하위 클래스로 치환 (Replace Type Code With Subclass) (0) | 2020.02.03 |
댓글 영역