Decorator Pattern 이란?
기존의 기능에 새로운 기능을 추가하고 싶을 경우, 새로운 기능을 Decorator로 만들어서 추가하는 방식
기본 기능에 추가할 수 있는 기능의 종류가 많은 경우, 각 추가 기능을 Decorator 클래스로 정의한 후 필요한 Decorator 객체를 조합함으로써 추가 기능의 조합을 설계
- Component: 기본 기능을 뜻하는 ConcreteComponent와 추가 기능을 뜻하는 Decorator의 공통 기능을 정의. Client는 Component를 통해 실제 객체 사용
- ConcreteComponent: 기본 기능을 구현하는 클래스
- Decorator: 많은 수가 존재하는 구체적인 Decorator 의 공통 기능 제공
- ConcreteDecoratorA, ConcreteDecoratorB : Decorator의 하위 클래스로 기본 기능에 추가되는 개별적인 기능 구현한 클래스
Decorator Pattern 구현
교재 예시: 네비게이션 SW 에서 도로 표시하는 기능
- 기본 기능 : 도로를 간단한 선으로 표시
- 추가 기능 : 도로의 차선 표시, 교통량 표시 등등
구현방법 ) 상속을 통한 기능 확장 (Decorate pattern 사용 x)
- 기본 도로 표시 클래스 : RoadDisplay
- 기본 도로 표시 + 차선 표시 클래스 : RoadDisplayWithLane
public class RoadDisplay { // 기본 도로 표시 클래스
public void draw(){
System.out.printnln("기본 도로 표시");
}
}
public class RoadDisplayWithLane extends RoadDisplay {
public void draw() {
super.draw();
drawLane();
}
private void drawLane(){
System.out.println("차선 표시");
}
}
문제점
1) 또다른 도로 표시 기능을 추가로 구현하고 싶은 경우
→ 상속을 통한 기능의 확장은 각 기능별로 클래스를 추가해야함
2) 여러 가지 추가 기능을 조합해 제공하고 싶은 경우
→ 추가되는 기능의 조합별로 하위 클래스를 구현해야하는 문제
- ex) 기본 도로 표시 기능에 차선 표시, 교통량 표시, 교차로 표시, 단속 카메라 표시의 4가지 추가 기능이 있을 때 추가 기능의 모든 조합은 15가지가 된다.
문제 해결
Decorate pattern을 통한 확장 : 각 추가 기능별로 개별적인 클래스를 설계하고 기능을 조합할 때 각 클래스의 객체 조합을 이용
- Component 역할: Display 클래스
- ConcreteComponent 역할: RoadDisplay 클래스
- Decorator 역할: DisplayDecorator 클래스
- ConcreteDecorator 역할 : LaneDecorator 클래스, TrafficDecorator 클래스
public class Display {
public abstract void draw();
}
public class RoadDisplay extends Display { // 기본 도로 표시 클래스
public void draw() {
System.out.println("기본 도로 표시");
}
}
public abstract class DisplayDecorator extends Display { // 다양한 추가 기능에 대한 공통 클래스
private Display decoratedDisplay;
public DisplayDecorator(Display decoratedDisplay){
this.decoratedDisplay = decoratedDisplay;
}
public void draw(){
decoratedDisplay.draw();
}
}
public class LaneDecorator extends DisplayDecorator { // 차선 표시를 추가하는 클래스
public LaneDecorator(Display decoratedDisplay){
super(decoratedDisplay);
}
public void draw(){
super.draw();
drawLane();
}
public void drawLane(){
System.out.println("차선 표시");
}
}
public class TrafficDecorator extends DisplayDecorator { //교통량 표시를 추가하는 클래스
public TrafficDecorator(Display decoratedDisplay){
super(decoratedDisplay);
}
public void draw(){
super.draw();
drawTraffic();
}
private void drawTraffic(){
System.out.println("교통량 표시");
}
}
public class Client {
public static void main(String args[]){
Display road = new RoadDisplay(); // 기본 도로 표시
road.draw();
Display roadWithLane = new LaneDecorator(new RoadDisplay());
roadWithLane.draw(); // 기본 도로표시 + 차선 표시
Display roadWithLaneAndTraffic = new TrafficDecorator(new LaneDecorator(new RoadDisplay()));
roadWithLaneAndTraffic.draw(); // 추가 기능들의 조합
}
}
→ Client 클래스는 동일한 Display 클래스만을 통해 일관성 있는 방식으로 도로 정보를 표시할 수 있다
'Design pattern' 카테고리의 다른 글
[Desigan Pattern] Factory Method Pattern (0) | 2022.08.17 |
---|---|
[Design Pattern] Template Method Pattern (0) | 2022.08.14 |
[Design Pattern] Observer Pattern (0) | 2022.08.04 |
[Design Pattern] Command Pattern (0) | 2022.08.01 |
[Design Pattern] State Pattern (0) | 2022.07.25 |