E D R , A S I H C RSS

Delegation Pattern

클래스에 대해 기능을 확장하는 두가지 방법중 하나이다. 하나는 상속이고 하나는 위임(Delegation) 이다. 상속을 하지 않아도 해당 클래스의 기능을 확장시킬 수 있는 방법이 된다.

또한, 클래스 하나가 방대해질때, 적절하게 그 클래스의 책임을 다른 클래스들에게 위임해주는 것은 Refactoring 의 방법이 된다.

ObjectOrientedProgramming 을 할때 자주 쓰이는 코딩 스타일. 아마 사람들이 무의식중에 자주 쓸 것이다.

example) 예전에 VonNeumannAirportJuNe1002 가 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;
	}
}


DelegationPattern을 쓸 때 중요한 점은, DelegationPattern을 사용하는 클래스의 클라이언트는 그 클래스가 Delegation을 쓰는지 안쓰는지 몰라야 한다는 것이다. 즉, 우리에게 있어 DelegationPattern이 사용된 클래스는 여느 클래스와 동일하게 인식되고 사용되어져야 한다. 게을러서 남에게 자신의 숙제를 위임하는 학생은 절대 남들에게 그 사실을 노출해선 안된다.

ResponsibilityDrivenDesign , Refactoring, DelegationPattern 을 꾸준히 지켜주면 좋은 코드가 나올 수 있다. (DesignPattern 이 유도되어짐)


전에 SE 수업중에 컴포넌트모델의 필요성을 이야기하던중 '상속으로의 재사용이 어렵기 때문에' 이야기를 하셨는데, 왜 대안 중 하나로서의 Delegation 에 대한 언급이 전혀 없으셨는지 모르겠다. Delegation 만 잘 이해해도 준 컴포넌트 스타일의 모듈화 프로그래밍을 잘 진행할 수 있고, 사람들 간의 작업분담도 잘 이끌어 낼 수 있을건데.. --1002

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-05-27 07:09:19
Processing time 0.0124 sec