코드 디자인 패턴/java
[java & 디자인 패턴] Decorator 패턴 정리
tea-tea
2024. 7. 17. 07:04
개념
이 패턴은 객체의 동작을 동적으로 추가하기 위해 사용한다.
기본적으로 자바는 클래스간에 상속으로 확장 방식을 지원하지만 단일 상속이 중심이라 한계가 존재하는데, 이 패턴은 이런 문제를 해결해줄 수 있다.
장점
- 유연한 기능 확장(상속 대체): 객체의 기능을 동적으로 추가하거나 변경하는 유연성 제공
- 코드 재사용성 증가: 여러 데코레이터를 조합하여 다양한 기능을 재사용할 수 있습니다.
- 동적 결합 : 클래스 상속처럼 컴파일 시점에 확장이 아니라 런타임 후 동적으로 확장 가능
단점
- 많은 객체 생성 | 데코레이터 패턴은 많은 추가 객체 및 인스턴스를 늘리며 setter도 복잡하여서 코드가 많아진다. 그래서 팩토리 패턴이나 빌더 패턴과 같이 사용한다.
- 디버깅 어려움 | 많은 데코레이터가 중첩되면 디버깅이 어려워진다. 구상 구성요소(concrete component)의 형식을 알아내서 그에 따라 작업을 처리하는 코드에는 적용 불가. 즉, 기존 클래스를 래핑하는 과정에서 사양이 달라 질수 있음(데코레이터 패턴을 적용하여 'A'를 '가'로 한 번 감싸게 되면 사용할 때 '가'인것은 알 수 있지만 이게 A로 만든 것인지 B로 만든 것인지 알 수 없음)
구현
Component (구성 요소)
기본 단위 기능을 구현하기 위한 인터페이스 또는 추상 클래스
public abstract class ABScharacter {
protected String name;
public String getName() {
return this.getName();
}
public abstract void interActNPC();
}
ConcreteComponent (구체적인 구성 요소)
Component를 구현한 실제 객체. 기본적인 기능 제공
public class Character extends ABScharacter {
public Character(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
@Override
public void interActNPC() {
// TODO Auto-generated method stub
System.out.println("npc와 반갑게 이야기를 나눕니다");
}
}
Decorator (데코레이터)
Component 인터페이스를 구현하고, 구성 요소를 포함하는 추상 클래스
기능을 확장하기 위해 메서드를 재정의
import case1.prac1.base.ABScharacter;
public abstract class Decorator extends ABScharacter {
public abstract String getName();
}
ConcreteDecorator (구체적인 데코레이터): Decorator를 구현한 클래스
원래 구성요소의 인터페이스 사양을 구현하면서 기존의 구현 클래스와 메소드를 이용해 확장한다.
import case1.prac1.base.ABScharacter;
public class warrior extends Decorator {
private ABScharacter character;
public warrior(ABScharacter abScharacter) {
// TODO Auto-generated constructor stub
this.character = abScharacter;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return this.character.getName() + " warrior";
}
@Override
public void interActNPC() {
// TODO Auto-generated method stub
this.character.interActNPC();
System.out.println("npc가 기사에게 호감을 보입니다.");
}
}