기존 클래스를 확장하는 것이 아니라 재사용하고 싶은 클래스를 멤버변수로 선언
새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조.
새 클래의 인스턴스 메서드들은 기존 클래스에 대응하는 메서드를 호출해 그 결과를 반환 한다.
기존 클래스의 구현이 바뀌거나, 새로운 메서드가 생기더라도 아무런 영향을 받지 않는다.
명시적으로 바뀐 부분을 알아 차릴 수 있다. ( ex) Set[E] 의 새로운 메서드가 생성 될 시)
// 코드 18-3 재사용할 수 있는 전달 클래스 (118쪽)
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) { this.s = s; }
public void clear() { s.clear(); }
public boolean contains(Object o) { return s.contains(o); }
public boolean isEmpty() { return s.isEmpty(); }
public int size() { return s.size(); }
public Iterator<E> iterator() { return s.iterator(); }
public boolean add(E e) { return s.add(e); }
public boolean remove(Object o) { return s.remove(o); }
public boolean containsAll(Collection<?> c)
{ return s.containsAll(c); }
public boolean addAll(Collection<? extends E> c)
{ return s.addAll(c); }
public boolean removeAll(Collection<?> c)
{ return s.removeAll(c); }
public boolean retainAll(Collection<?> c)
{ return s.retainAll(c); }
public Object[] toArray() { return s.toArray(); }
public <T> T[] toArray(T[] a) { return s.toArray(a); }
@Override public boolean equals(Object o)
{ return s.equals(o); }
@Override public int hashCode() { return s.hashCode(); }
@Override public String toString() { return s.toString(); }
}
p119, 데코레이터 패턴
p119, 컴포지션과 전달 조합은 넓은 의미로 위임(delegation)이라고 부른다.
p119, 콜백 프레임워크와 셀프 문제
기존 코드를 변경하지 않고 부가 기능을 추가하는 패턴
상속이 아닌 위임을 사용해서 보다 유연하게(런타임에) 부가 기능을 추가하는 것도 가능하다
최소한의 인터페이스를 컴포넌트를 정의**(한가지의 예시일 뿐)**

콜백 프레임워크와 래퍼를 같이 사용했을 때 발생할 수 있는 문제
콜백 함수: 다른 함수(A)의 인자로 전달된 함수(B)로, 해당 함수(A) 내부에서 필요 한 시점에 호출 될 수는 함수 (B)를 말한다.
래퍼로 감싸고 있는 내부 객체가 어떤 클래스(A)의 콜백으로(B) 사용되는 경우에 this를 전달한다면, 해당 클래스(A)는 래퍼가 아닌 내부 객체를 호출한다. (SELF 문제)
class BobFunction implements FunctionToCall {
private final Service service;
public BobFunction(Service service) {
this.service = service;
}
@Override
public void call() {
System.out.println("밥을 먹을까..");
}
**@Override
public void run() {
this.service.run(this); // this 는 BobFunction 이다.
}**
}
==
public class BobFunctionWrapper implements FunctionToCall {
private final BobFunction bobFunction;
public BobFunctionWrapper(BobFunction bobFunction) {
this.bobFunction = bobFunction;
}
@Override
**public void call() {
this.bobFunction.call(); // 위임 후 아래의 println 실행하는 것이 기대값
System.out.println("커피도 마실까..."); // 호출되지 않음
}**
@Override
public void run() {
this.bobFunction.run();
}
}
===
public class Service {
public void run(FunctionToCall functionToCall) {
System.out.println("뭐 좀 하다가...");
functionToCall.call();
}
public static void main(String[] args) {
Service service = new Service();
BobFunction bobFunction = new BobFunction(service);
BobFunctionWrapper bobFunctionWrapper = new BobFunctionWrapper(bobFunction);
**bobFunctionWrapper.run(); // .call() 메서드를 호출해야 콜백 문제 해결**
}
}