어떤 기능에 추가적으로 기능을 덧붙일 때 해당 기능을 decorater 형태로 덧붙이는 방식.
객체의 결합을 통해 기능을 동적으로 유연하게 확장 할 수 있게 해주는 패턴.
기능이 정해져 있는 객체가 아닌, 동적으로 기능을 조합하여 객체를 만드는 것이 가능해짐.
예제를 통해 위 표현을 이해해보자
맥날 초코콘 만들기
상속으로 구현된 서브클래스를 이용한 초코콘과 데코레이턴 패턴을 적용한 초코콘을 비교하여 이해해보면 데코레이터 패턴의 이점을 더 잘 알 수 있다.
// 아이스크림 클래스
public class Icecream {
public void make() {
System.out.println("아이스크림");
}
}
// 아이스크림 클래스를 상속받은 초코콘
public class IcecreamWithChoco extends Icecream{
@Override
public void make() {
super.make();
addChoco();
}
private void addChoco() {
System.out.println("+ 초코");
}
}
// 아이스크림 클래스를 상속받은 바나나콘
public class IcecreamWithBanana extends Icecream{
@Override
public void make() {
super.make();
addBanana();
}
private void addBanana() {
System.out.println("+ 바나나");
}
}
// 초코+바나나 콘 조합
public class IcecreamWithChocoBanana extends Icecream{
@Override
public void make() {
super.make();
addBanana();
addChoco()
}
private void addBanana() {
System.out.println("+ 바나나");
}
private void addChoco() {
System.out.println("+ 초코");
}
}
// 만들기
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
Icecream icecream = new Icecream();
icecream.make();
System.out.println("-----");
// 초코콘
IcecreamWithChoco icecreamWithChoco = new IcecreamWithChoco();
icecreamWithChoco.make();
System.out.println("-----");
// 초코바나나콘
IcecreamWithChocoBanana icecreamWithChocoBanana = new IcecreamWithChocoBanana();
icecreamWithChocoBanana.make();
System.out.println("-----");
}
위와 같이 만들 경우 !
새로운 콘의 조합이 만들어질 때마다 새로운 클래스를 생성해야함
// 아이스크림 추상클래스
public abstract class Icecream {
public abstract void make();
}
// default cone
public class Cone extends Icecream {
@Override
public void make() {
System.out.println("콘 추가");
}
}
// 토핑 데코레이터 클래스
public class ToppingDecorator extends Icecream {
private Icecream icecream;
public ToppingDecorator(Icecream icecream) {
this.icecream = icecream;
}
@Override
public void make() {
icecream.make();
}
}
// 바나나 토핑
public class BananaDecorator extends ToppingDecorator {
public BananaDecorator(Icecream icecream) {
super(icecream);
}
@Override
public void make() {
super.make();
addBanana();
}
private void addBanana() {
System.out.println("+ 바나");
}
}
// 초코 토핑
public class ChocoDecorator extends ToppingDecorator {
public ChocoDecorator(Icecream icecream) {
super(icecream);
}
@Override
public void make() {
super.make();
addChoco();
}
private void addChoco() {
System.out.println("+ 초코");
}
}
public static void main(String[] args) {
// 초코콘
Icecream chocoCone = new ChocoDecorator(new Cone());
chocoCone.make();
System.out.println("-----");
// 초코+바나나콘
Icecream chocoBananaCone = new ChocoDecorator(new BananaDecorator(new Cone()));
chocoBananaCone.make();
}
데코레이터 패턴의 경우 초코+바나나콘을 만들더래도 초코+바나나 객체를 새로 생성하지 않아도 된다. 데코레이터 클래스를 이용하여 하위 데코클래스의 조합을 통해 생성이 가능하다.