데코레이터 패턴: 기본 기능에 옵션을 추가하는 경우 유용한 패턴
기존 코드: RoadDisplay는 기본 도로 표시 기능을 제공하는 클래스이다. RoadDisplayWithLane은 기본 도로 표시 기능에 추가적으로 차선을 표시하는 클래스이다.

// 기본 도료 표시 클래스
class RoadDisplay{
public void draw() {
System.out.println("도로 기본 표시");
}
}
// 기본 도로 표시 + 차선 표시 클래스
class RoadDisplayWithLane extends RoadDisplay{
public void draw() {
super.draw();
drawLane();
}
private void drawLane() {
System.out.println("차선 표시");
}
}
public class Client{
public static void main(String[] args) {
RoadDisplay road=new RoadDisplay();
road.draw();
RoadDisplay roadWithLane=new RoadDisplayWithLane();
roadWithLane.draw();
}
}
// 기본 도료 표시 클래스
class RoadDisplay{
public void draw() {
System.out.println("도로 기본 표시");
}
}
// 기본 도로 표시 + 차선 표시 클래스
class RoadDisplayWithLane extends RoadDisplay{
public void draw() {
super.draw();
drawLane();
}
private void drawLane() {
System.out.println("차선 표시");
}
}
public class Client{
public static void main(String[] args) {
RoadDisplay road=new RoadDisplay();
road.draw();
RoadDisplay roadWithLane=new RoadDisplayWithLane();
roadWithLane.draw();
}
}
// 기본 도료 표시 클래스 class RoadDisplay{ public void draw() { System.out.println("도로 기본 표시"); } } // 기본 도로 표시 + 차선 표시 클래스 class RoadDisplayWithLane extends RoadDisplay{ public void draw() { super.draw(); drawLane(); } private void drawLane() { System.out.println("차선 표시"); } } public class Client{ public static void main(String[] args) { RoadDisplay road=new RoadDisplay(); road.draw(); RoadDisplay roadWithLane=new RoadDisplayWithLane(); roadWithLane.draw(); } }
문제점: 옵션이 추가될 때마다 클래스가 한 개씩 늘어난다. 예를 들어 ‘기본 도로 표시’ 기능에 ‘교통량 표시’를 하는 옵션이 추가되면 ‘RoadDisplayWithTraffic’ 클래스를 만들어야 된다. 또한 ‘기본 도로 표시+차선 표시+교통량 표시’를 하려면 ‘RoadDisplayWithLaneAndTraffic’ 클래스를 만들어야 된다.
해결책: 데코레이터 객체를 사용한다. 데코레이터는 기본 기능(Original)을 데코레이션할 수도 있고, 또 다른 데이코레이터를 데코레이션할 수도 있다.

Decorator 객체의 draw() 메소드는 슈퍼 클래스의 draw() 메소드를 먼저 호출하는 구조를 지닌다.
ex) LaneDecorator의 draw()는 DisplayDecorator의 draw()를 호출함으로써 RoadDisplay의 draw() 기능을 처리한 뒤 자신의 기능을 수행한다.

abstract class Display{
public abstract void draw();
}
class RoadDisplay extends Display{
public void draw() {
System.out.println("기본 도로 표시");
}
}
// 다양한 추가 기능에 대한 공통 클래스
abstract class DisplayDecorator extends Display{
private Display decoratedDisplay;
public DisplayDecorator(Display decoratedDisplay) {
this.decoratedDisplay = decoratedDisplay;
}
public 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("\t차선 표시");
}
}
class TrafficDecorator extends DisplayDecorator{
public TrafficDecorator(Display decoratedDisplay) {
super(decoratedDisplay);
}
public void draw() {
super.draw();
drawTraffic();
}
private void drawTraffic() {
System.out.println("\t교통량 표시");
}
}
public class Client{
public static void main(String[] args) {
Display road=new RoadDisplay();
road.draw();
Display roadWithLane=new LaneDecorator(new RoadDisplay());
roadWithLane.draw();
Display roadWithTraffic=new TrafficDecorator(new RoadDisplay());
roadWithTraffic.draw();
}
}
abstract class Display{
public abstract void draw();
}
class RoadDisplay extends Display{
public void draw() {
System.out.println("기본 도로 표시");
}
}
// 다양한 추가 기능에 대한 공통 클래스
abstract class DisplayDecorator extends Display{
private Display decoratedDisplay;
public DisplayDecorator(Display decoratedDisplay) {
this.decoratedDisplay = decoratedDisplay;
}
public 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("\t차선 표시");
}
}
class TrafficDecorator extends DisplayDecorator{
public TrafficDecorator(Display decoratedDisplay) {
super(decoratedDisplay);
}
public void draw() {
super.draw();
drawTraffic();
}
private void drawTraffic() {
System.out.println("\t교통량 표시");
}
}
public class Client{
public static void main(String[] args) {
Display road=new RoadDisplay();
road.draw();
Display roadWithLane=new LaneDecorator(new RoadDisplay());
roadWithLane.draw();
Display roadWithTraffic=new TrafficDecorator(new RoadDisplay());
roadWithTraffic.draw();
}
}
abstract class Display{ public abstract void draw(); } class RoadDisplay extends Display{ public void draw() { System.out.println("기본 도로 표시"); } } // 다양한 추가 기능에 대한 공통 클래스 abstract class DisplayDecorator extends Display{ private Display decoratedDisplay; public DisplayDecorator(Display decoratedDisplay) { this.decoratedDisplay = decoratedDisplay; } public 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("\t차선 표시"); } } class TrafficDecorator extends DisplayDecorator{ public TrafficDecorator(Display decoratedDisplay) { super(decoratedDisplay); } public void draw() { super.draw(); drawTraffic(); } private void drawTraffic() { System.out.println("\t교통량 표시"); } } public class Client{ public static void main(String[] args) { Display road=new RoadDisplay(); road.draw(); Display roadWithLane=new LaneDecorator(new RoadDisplay()); roadWithLane.draw(); Display roadWithTraffic=new TrafficDecorator(new RoadDisplay()); roadWithTraffic.draw(); } }