* 23.03.29 코드수정
Delegate 패턴이 '헤드퍼스트 디자인 패턴' 도서에 나와있지 않아서 정리해보고자 한다.
아무래도 Decorator 패턴 또는 strategy 패턴과 비슷하기 때문일까?
또한, 이 Delegate 패턴이 Decorator 패턴이랑 혼동된 블로그 글도 나와있기에 힘들었다.
그리고 Strategy 패턴과 유사한 부분이 있어서 이 점도 많이 헷갈렸다.
🤔 Delegate 패턴이란?
- 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. 주문 처리시, 여러 단계로 나누어 각 단계에서 다른 로직을 처리할 때
🧐 마무리
delegate 패턴이 다른 패턴들과 유사한 부분들이 많지만 그것이 나온 목적에 따라서 적용하면 될 것 같다.
따라서 내가 가진 기능 중에 일부분을 다른 객체에 위임시킬 때 사용하는 것이 델리게이트 패턴이라고 생각하자.
https://java-design-patterns.com/patterns/delegation/#explanation
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
Decorator(데코레이터) 패턴이란? (0) | 2023.04.18 |
---|---|
Observer(옵저버) 패턴이란? (0) | 2023.03.30 |
Strategy Pattern(전략 패턴)이란? (0) | 2023.03.21 |