클래스에 대해 기능을 확장하는 두가지 방법중 하나이다. 하나는 상속이고 하나는 위임(Delegation) 이다. 상속을 하지 않아도 해당 클래스의 기능을 확장시킬 수 있는 방법이 된다.
또한, 클래스 하나가 방대해질때, 적절하게 그 클래스의 책임을 다른 클래스들에게 위임해주는 것은
Refactoring 의 방법이 된다.
example) 예전에
VonNeumannAirport 을
JuNe 과
1002 가 Pair 하던중
JuNe 이 작성했던 Refactoring 으로서의 Delegation.
~cpp
public class Airport {
private int _traffic;
private int [] _arrivalGate;
private int [] _departureGate;
private PassengerSet psg;
public int getTraffic() {
ListIterator iter = psg.passengers.listIterator();
int [] passenger;
while (iter.hasNext()) {
passenger = (int [])iter.next();
movePassenger(passenger[0],
passenger[1],
passenger[2]);
}
return _traffic;
}
public void setArrivalGates(int [] aCity) {
_arrivalGate = aCity;
}
public void setDepartureGates(int [] aCity) {
_departureGate = aCity;
}
public int [] getArrivalGates() {
return _arrivalGate;
}
public int [] getDepartureGates() {
return _departureGate;
}
public int getDistance(int fromCity, int toCity){
int distance=java.lang.Math.abs(_getArrivalCityGate(fromCity)
-_getDepartureCityGate(toCity))+1;
return distance;
}
private void movePassenger(int fromCity, int toCity, int aNumber) {
_traffic+=getDistance(fromCity,toCity)*aNumber;
}
public void setPassengers(PassengerSet psg) {
this.psg=psg;
}
}
여기까지는 Airport 이다. 하지만
VonNeumannAirport 문제에서도 보듯, 실제 Input 에 대해서 Configuration 은 여러 Set 이 나온다.
이 기능을 추가하기 위해 일단 Airport Code 를 Refactoring 하기로 했다. 이를 위해 Airport 의 기능중 Configuration 과 관련된 기능에 대해 Configuration 을 Extract 하고, 내부적으로는 Delegation 함으로서 외부적으로 보이는 기능에 대해서는 일관성을 유지한다. (Test Code 가 일종의 Guard 역할을 했었음)
~cpp
import java.util.ListIterator;
class Configuration {
private int [] _arrivalGate;
private int [] _departureGate;
private int id;
public void setArrivalGates(int [] aCity) {
_arrivalGate=aCity;
}
public void setDepartureGates(int [] aCity) {
_departureGate=aCity;
}
public int [] getArrivalGates() {
return _arrivalGate;
}
public int [] getDepartureGates() {
return _departureGate;
}
public int getDistance(int fromCity, int toCity){
int distance=java.lang.Math.abs(_getArrivalCityGate(fromCity)
-_getDepartureCityGate(toCity))+1;
return distance;
}
public int _findInIntArray(int anInt,int [] anArray) {
for (int i=0;i<anArray.length;i++) {
if (anArray[i] == anInt) return i+1;
}
return -1;
}
public int _getArrivalCityGate(int aCity) {
return _findInIntArray(aCity,getArrivalGates());
}
public int _getDepartureCityGate(int aCity) {
return _findInIntArray(aCity,getDepartureGates());
}
public int getId() {
return id;
}
public void setId(int anId) {
id=anId;
}
}
public class Airport {
private int _traffic;
private int [] _arrivalGate;
private int [] _departureGate;
private PassengerSet psg;
private Configuration conf=new Configuration();
public int getTraffic() {
ListIterator iter = psg.passengers.listIterator();
int [] passenger;
while (iter.hasNext()) {
passenger = (int [])iter.next();
movePassenger(passenger[0],
passenger[1],
passenger[2]);
}
return _traffic;
}
public void setArrivalGates(int [] aCity) {
conf.setArrivalGates(aCity);
}
public void setDepartureGates(int [] aCity) {
conf.setDepartureGates(aCity);
}
public int [] getArrivalGates() {
return conf.getArrivalGates();
}
public int [] getDepartureGates() {
return conf.getDepartureGates();
}
public int getDistance(int fromCity, int toCity){
return conf.getDistance(fromCity,toCity);
}
private void movePassenger(int fromCity, int toCity, int aNumber) {
_traffic+=getDistance(fromCity,toCity)*aNumber;
}
public void setPassengers(PassengerSet psg) {
this.psg=psg;
}
}
전에 SE 수업중에 컴포넌트모델의 필요성을 이야기하던중 '상속으로의 재사용이 어렵기 때문에' 이야기를 하셨는데, 왜 대안 중 하나로서의
Delegation 에 대한 언급이 전혀 없으셨는지 모르겠다. Delegation 만 잘 이해해도 준 컴포넌트 스타일의 모듈화 프로그래밍을 잘 진행할 수 있고, 사람들 간의 작업분담도 잘 이끌어 낼 수 있을건데.. --
1002