"Delegate"라는 개념은 다양한 프로그래밍 언어와 프레임워크에서 사용되며, 메서드 호출을 다른 객체나 메서드로 위임하는 패턴을 의미합니다. Java에서의 위임(delegate)은 특정 인터페이스의 메서드를 직접 구현하지 않고, 그 구현을 다른 객체에 위임(delegate)하는 방식으로 구현할 수 있습니다. 이를 통해 코드 재사용성과 유연성을 높일 수 있습니다.
Delegate Pattern
- delegate는 '위임하다' 라는 사전적 의미
- 즉, 객체가 자신의 기능을 다른 객체에게 위임하여 기능을 실행하는 디자인 패턴
- 객체 간의 결합도를 낮춰서 유지보수성과 확장성을 높이는데 사용됨
예시 :
- A는 B의 기능을 사용하고 싶을 때, A가 B의 기능을 직접 구현하지 않고, C에게 위임(delegate)하여 구현하는 것
- 이 때 C를 델리게이트(delegate) 객체 or 대리자 객체라고 함
- 델리게이트 객체는 B의 기능을 대신 구현하기 때문에, A는 C를 통해 B의 기능을 호출할 수 있음
- 이를 통해 A는 B의 기능을 사용할 수 있으면서도, A와 B의 결합도를 낮출 수 있음
위 예시를 좀 더 구체적으로 말해보면 다음과 같습니다 :
- A가 동물의 울음소리를 출력하고 싶음
- B는 다양한 동물이 존재함
- A는 B에 직접적으로 접근하지 않고, 울음소리를 출력하는 기능을 C에게 위임
- C는 B에서 적절한 동물의 울음소리를 선택하여 출력할 수 있음
- 이처럼 A와 B의 결합도를 낮추면서 다양한 동물의 울음소리를 출력할 수 있음
Delegate 패턴을 적용한 예시코드
public enum AnimalKind {
CAT, DOG
}
public interface Animal {
void makeSound();
AnimalKind getKind();
boolean isSameKind(AnimalKind kind);
}
// B
public class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("야옹");
}
@Override
public AnimalKind getKind() {
return AnimalKind.CAT;
}
@Override
public boolean isSameKind(AnimalKind kind) {
return AnimalKind.CAT.equals(kind);
}
}
// B
public class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("멍멍");
}
@Override
public AnimalKind getKind() {
return AnimalKind.DOG;
}
@Override
public boolean isSameKind(AnimalKind kind) {
return AnimalKind.DOG.equals(kind);
}
}
// C
public class AnimalDelegator {
private final List<Animal> animals;
public AnimalDelegator() {
animals = new ArrayList<>();
animals.add(new Cat());
animals.add(new Dog());
}
public void makeSound(AnimalKind kind) {
animals.stream()
.filter(animal -> animal.isSameKind(kind))
.forEach(Animal::makeSound);
}
}
// A
public class Client {
public static void main(String[] args) {
AnimalDelegator delegator = new AnimalDelegator();
delegator.makeSound(AnimalKind.CAT); // "야옹" 출력
delegator.makeSound(AnimalKind.DOG); // "멍멍" 출력
}
}
- A는 `Client` 클래스
- B는 `Cat`와 `Dog` 클래스
- C는 `AnimalDelegator` 클래스
- A는 C의 makeSound()를 호출함으로써 동물의 울음소리를 출력
- A는 B에게 직접적으로 접근하지 않고, 울음소리를 출력하는 기능을 C에게 위임
- C는 B에서 적절한 동물의 울음소리를 선택하여 출력
Delegate 패턴과 Decorator 패턴 차이점
Decorator 패턴
- 객체에 동적으로 기능을 추가 또는 변경할 수 있는 패턴
- "객체가 가진 기본 기능을 변경하지 않으면서 기능을 추가하는 것"이 핵심
- 기본 객체를 래핑(Wrapping)하여 추가적인 기능을 제공하고, 이를 계속 래핑하여 여러 개의 데코레이터가 중첩될 수 있음
- 상속을 이용하여 구현하는 경우가 많음
Delegate 패턴
- 객체의 행위를 다른 객체에 위임하는 패턴
- "객체가 다른 객체에게 일부 기능을 위임할 수 있도록 하는 것"이 핵심
- 객체가 직접적으로 기능을 수행하는 것 대신에 다른 객체에 해당 기능을 위임
- 인터페이스를 이용하여 구현하는 경우가 많음
결론
- Decorator 패턴은 객체의 기능을 동적으로 확장하는 것이 목적
- 원래 객체는 변하지 않으며 새로운 Decorator 객체를 사용할 수 있음
- Delegate 패턴은 객체의 동작을 다른 객체에 위임하는 것이 목적
- 원래 객체의 동작이 변경될 수 있음
Delegate 패턴과 Strategy 패턴 차이점
Strategy 패턴
- 동일한 문제를 해결하기 위한 알고리즘을 캡슐화하고, 이를 교환해서 사용하는 패턴
- 즉, 알고리즘을 인터페이스로 정의하고 이를 구현한 다양한 전략 객체를 필요에 따라 교체하여 사용
- 전략 객체들은 같은 문제를 해결하기 위한 다양한 알고리즘으로, 서로 교체 가능하며, 동적으로 알고리즘을 변경 가능
결론
- Stragegy 패턴은 실행 중에 알고리즘을 변경하기 위한 패턴
- e.g. 할인 적용 시, 다양한 할인 전략에 따라 가격이 달라질 때
- Delegate 패턴은 객체의 동작을 다른 객체에 위임하여 사용하기 위한 패턴
- e.g. 주문 처리시, 여러 단계로 나누어 각 단계에서 다른 로직을 처리할 때
'Spring Study' 카테고리의 다른 글
Mixin Pattern (자바에선 다중상속 허용X -> 믹스인디자인패턴으로 흉내) (0) | 2024.08.28 |
---|---|
Proxy Pattern ( Delegate Pattern 에서의 '위임' 과의 차이 ) (0) | 2024.08.28 |
[ AOP 포인트컷 ] 클래스 필터(ClassFilter)와 메서드 매처(MethodMatcher) (0) | 2024.08.27 |
FactoryBean과 ProxyFactoryBean (0) | 2024.08.26 |
Aspect 와 Aspect J 의 차이 (0) | 2024.08.23 |