JUINTINATION
데커레이터(Decorator) 패턴 본문
반응형
데커레이터 패턴이란?
기본 기능에 추가할 수 있는 기능의 종류가 많은 경우 기본 기능에 추가될 수 있는 많은 수의 부가 기능에 대해서 다양한 조합을 동적으로 구현할 수 있는 패턴이다.
다음과 같이 도로를 여러 가지 표시하는 프로그램이 있다고 하자.
public class Client {
public static void main(String[] args) {
RoadDisplay roadDisplay = new RoadDisplay();
roadDisplay.draw();
RoadDisplayWithLane roadDisplayWithLane = new RoadDisplayWithLane();
roadDisplayWithLane.draw();
}
}
class RoadDisplay {
public void draw() {
System.out.println("기본 도로 표시");
}
}
class RoadDisplayWithLane extends RoadDisplay {
@Override
public void draw() {
super.draw();
drawLane();
}
private void drawLane() {
System.out.println("차선 표시");
}
}
- 위 코드의 문제점
- 여러 가지 추가 기능을 조합하여 도로를 표시하는 방법을 바꾸고 싶다면 각 기능을 중복되게 작성하여 각각의 클래스를 만들어야 한다.
경우 | 기본 기능 도로 표시 | 추가 기능 | 클래스 이름 | ||
차선 표시 | 교통량 표시 | 교차로 표시 | |||
1 | O | RoadDisplay | |||
2 | O | O | RoadDisplayWithLane | ||
3 | O | O | RoadDisplayWithTraffic | ||
4 | O | O | RoadDisplayWithCrossing | ||
5 | O | O | O | RoadDisplayWithLaneTraffic | |
6 | O | O | O | RoadDisplayWithLaneCrossing | |
7 | O | O | O | RoadDisplayWithTrafficCrossing | |
8 | O | O | O | O | RoadDisplayWithLaneTrafficCrossing |
이를 해결하기 위해 다음과 같이 추가 기능별로 개별적인 클래스를 설계하고 이를 조합한다.
public class Client {
public static void main(String[] args) {
Display roadWithLaneTrafficCrossingDisplay = new LaneDecorator(new TrafficDecorator(new CrossingDecorator(new RoadDisplay())));
roadWithLaneTrafficCrossingDisplay.draw();
}
}
abstract class Display {
abstract void draw();
}
class RoadDisplay extends Display {
@Override
void draw() {
System.out.println("기본 도로 표시");
}
}
abstract class DisplayDecorator extends Display {
private Display decoratedDisplay;
public DisplayDecorator(Display decoratedDisplay) {
this.decoratedDisplay = decoratedDisplay;
}
@Override
void draw() {
decoratedDisplay.draw();
}
}
class LaneDecorator extends DisplayDecorator {
public LaneDecorator(Display decoratedDisplay) {
super(decoratedDisplay);
}
public void draw() {
super.draw();
drawLane();
}
private void drawLane() {
System.out.println("차선 표시");
}
}
class TrafficDecorator extends DisplayDecorator {
public TrafficDecorator(Display decoratedDisplay) {
super(decoratedDisplay);
}
public void draw() {
super.draw();
drawTraffic();
}
private void drawTraffic() {
System.out.println("교통량 표시");
}
}
class CrossingDecorator extends DisplayDecorator {
public CrossingDecorator(Display decoratedDisplay) {
super(decoratedDisplay);
}
public void draw() {
super.draw();
drawCrossing();
}
private void drawCrossing() {
System.out.println("교차로 표시");
}
}
데커레이터 패턴 컬레보레이션
Component : 기본 기능을 뜻하는 ConcreteComponent와 추가 기능을 뜻하는 Decorator의 공통 기능을 정의한 추상 클래스
ConcreteComponent : 기본 기능을 구현하는 클래스
Decorator : 추가 기능의 공통 기능을 정의한 추상 클래스
ConcreteDecorator : 기본 기능의 추가되는 개별적인 기능을 정의한 Decorator의 하위 클래스
데커레이터 패턴을 이용한 간단한 예제
다음과 같은 이메일 내용과 관련된 기능을 구현한 프로그램 코드와 클래스 다이어그램이 있을 때 데커레이터 패턴을 적용하여 프로그램 기능을 개선하라.
class BasicEMailContent {
private String content;
public BasicEMailContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
class ExternalEMailContent extends BasicEMailContent {
public ExternalEMailContent(String content) {
super(content);
}
@Override
public String getContent() {
return addDisclaimer(super.getContent());
}
private String addDisclaimer(String content) {
return content + " Company Disclaimer";
}
}
class SecureEMailContent extends BasicEMailContent {
public SecureEMailContent(String content) {
super(content);
}
@Override
public String getContent() {
return encrypt(super.getContent());
}
private String encrypt(String content) {
return content + " Encrypted";
}
}
- 위 코드의 문제점
- ExternalEMailContent와 SecureEMailContent의 조합을 추가하기 위해 각 기능을 중복되게 작성하여 새로운 클래스를 만들어야 한다.
이 문제를 해결하기 위해 다음과 같이 코드와 클래스 다이어그램을 수정해야 한다.
abstract class EMailContent {
public abstract String getContent();
}
class BasicEMailContent extends EMailContent {
private String content;
public BasicEMailContent(String content) {
this.content = content;
}
@Override
public String getContent() {
return content;
}
}
abstract class ContentDecorator extends EMailContent {
private EMailContent decoratedContent;
public ContentDecorator(EMailContent decoratedContent) {
this.decoratedContent = decoratedContent;
}
@Override
public String getContent() {
return decoratedContent.getContent();
}
}
class ExternalDecorator extends ContentDecorator {
public ExternalDecorator(EMailContent decoratedContent) {
super(decoratedContent);
}
@Override
public String getContent() {
return addDisclaimer(super.getContent());
}
private String addDisclaimer(String content) {
return content + " Company Disclaimer";
}
}
class SecureDecorator extends ContentDecorator {
public SecureDecorator(EMailContent decoratedContent) {
super(decoratedContent);
}
@Override
public String getContent() {
return encrypt(super.getContent());
}
private String encrypt(String content) {
return content + " Encrypted";
}
}
728x90
'JAVA객체지향디자인패턴' 카테고리의 다른 글
팩토리 메서드(Factory Method) 패턴 (1) | 2023.07.16 |
---|---|
템플릿 메서드(Template Method) 패턴 (0) | 2023.07.16 |
옵서버(Observer) 패턴 (0) | 2023.07.06 |
커맨드(Command) 패턴 (0) | 2023.07.06 |
스테이트(State) 패턴 (0) | 2023.07.06 |
Comments