데코레이터 패턴은 목표 객체의 부가적인 속성을 동적으로 표현해주기 위해 사용하는 디자인 패턴입니다.
동적으로 연결된다는 의미는 기능을 부가할 때, 어떤 방법과 순서에 따라서 연결되지 않는다는 것을 의미합니다.
자동차를 만들 때를 한번 생각해보죠.
자동차가 있으면, 네비게이션 달고, 스킨 튜닝하고, 썬루프 달고 하는 걸 순서대로 하지는 않겠죠?
사용자의 요구에 맞추어서 해주겠죠.
코드를 한번 봅시다.
public interface Car {
public void assemble();
}
public class BasicCar implements Car {
@Override
public void assemble() {
System.out.print("Basic Car.");
}
}
public class CarDecorator implements Car {
protected Car car;
public CarDecorator(Car c){
this.car=c;
}
@Override
public void assemble() {
this.car.assemble();
}
}
public class LuxuryCar extends CarDecorator {
public LuxuryCar(Car c) {
super(c);
}
@Override
public void assemble(){
super.assemble();
System.out.print(" Adding features of Luxury Car.");
}
}
public class SportsCar extends CarDecorator {
public SportsCar(Car c) {
super(c);
}
@Override
public void assemble(){
super.assemble();
System.out.print(" Adding features of Sports Car.");
}
}
부품(assemble)을 가지도록 설계한 Car 인터페이스가 있습니다.
그리고, 그 인터페이스를 구현한 BasicCar 클래스가 있습니다.
근데 차를 좀 꾸미고 싶어요. 화려한(Luxury) 차와 스포츠(Sports) 차
그래서 CarDecorator를 통해서 차를 좀 꾸미려고 합니다.
이 CarDecorator 가 꾸밀 수 있는 차는 Car 이기만 하면 어떤 차든 상관이 없습니다.
그래서 SportCar와 LuxuryCar의 부품을 제공해주는 클래스 두개를 만들었습니다.
SportsCar와 LuxuryCar는 엄밀히 말해선 차가 아닙니다. 부품을 제공해주는 클래스죠.
이런 부품을 통해 차를 꾸밀 수 있습니다.
밑의 코드를 한번 볼까요.
public class CarTest {
public static void main(String[] args) {
Car sportsCar = new SportsCar(new BasicCar());
sportsCar.assemble();
System.out.println("\n*****");
Car sportsLuxuryCar = new LuxuryCar(new SportsCar(new BasicCar()));
sportsLuxuryCar.assemble();
System.out.println("\n*****");
// 안되는 코드들
Car car = new LuxuryCar(new SportsCar());
Car car2 = new SportsCar(new LuxuryCar());
}
}
기본 차를 꾸미는 스포츠 차가 있습니다.
이 차는 기본차 + 스포츠 차의 부품 을 통해 스포츠차의 속성을 지닙니다.
밑에는 기본차 + 스포츠 차의 부품 + 화려한 차의 부품을 가지고 화려한 스포츠차를 만들었네요.
이렇듯 객체를 꾸미는 디자인 패턴을 데코레이션 패턴이라고 합니다.
이 패턴은 객체를 꾸미는 데에 상당히 유연하게 처리할 수 있다는 점이 장점입니다.
가장 중요한 점은 데코레이션은 순서에 상관없다는 점과, 꾸밀 속성을 가지는 기본 객체가 꼭 필요하다는 점입니다.
즉 위에서는 SportsCar를 LuxuryCar로 감싼 형태를 띠는데
new SportsCar(new LuxuryCar(new BasicCar()));
이렇게 반대로 해도 상관이 없습니다.
마지막에 감쌌다고 바로 안쪽에 위치한 객체에 의존하는 포괄적인 형태를 띠는 것이 아닙니다.
오직 기본객체만이 다른 객체들이 의존한 형태를 띱니다.
그래서 마지막에 보시다시피 기본객체가 누락된 코드들은
컴파일 에러가 뜨면서 작동하지 않게 끔 되어있습니다.
그림으로 본다면 이렇게 되겠네요.
사진 및 코드 출처: https://www.journaldev.com/1540/decorator-design-pattern-in-java-example
'프로그래밍 > Java' 카테고리의 다른 글
디자인 패턴 - 프록시 패턴(Proxy pattern) (0) | 2018.02.12 |
---|---|
이펙티브 자바 규칙 13 - 클래스와 멤버의 접근 권한은 최소화하라 (0) | 2018.02.10 |
자바 Exception 예외 (throwable, Error, Exception, RuntimeException) (0) | 2018.02.09 |