해당 포스트는 "자바 객체지향 디자인 패턴", "JAVA 언어로 배우는 디자인 패턴 입문" 책의 내용을 요약한 것이다.



※ 데코레이터(Decorator) 패턴

: 기존에 구현되어 있는 클래스에 추가할 수 있는 기능의 종류가 많을 경우 코드상에서 동적으로 기능을 추가하기 위한 패턴으로 데코레이터를 통해 클래스의 기능이 확장된다.

데코레이터가 적용된 대표적인 예로 자바 I/O가 있다.

Reader reader = new BufferedReader(new FileReader("파일명"));

FileReader 클래스가 BufferedReader 데코레이터 클래스를 통해 기능이 확장된 예이다.

 

 

ex)도로를 간단한 선으로 표시하는 기본적인 기능을 가진 네비게이션 SW로, 추가적으로 도로를 간단한 선뿐만 아니라 도로의 차선을 표시하는 추가 기능을 가진다.

public class RoadDisplay{
   public void draw(){
        System.out.println("기본 도로 표시");
   }
}

public class RoadDisplayWithLane extends RoadDisplay{
    public void draw(){
        super.draw();
        drawLane();        //추가적으로 차선을 표시
     }
    private void drawLane(){
        System.out.println("차선 표시");
    }
}

도로를 간단한 선으로 표시하는 RoadDisplay 클래스와 추가적으로 차선을 표시하는 RoadDisplayWithLane 클래스를 정의했다. RoadDisplayWithLane 클래스는 도로 표시 기능도 제공하므로 RoadDisplay 클래스의 하위 클래스로 구현했다.

 

 

- 문제점

또 다른 도로 표시 기능인 교통량 표시와 교차로 표시가 추가 되었다. 이 추가된 여러 가지 기능들을 조합해 제공하고 싶으면 어떻게 해야 할까? 예를 들어, 기본 도로 표시에 차선 표시 기능과 교통량 표시 기능을 함게 제공하고 싶다면 어떻게 해야 할까? 이럴 경우 RoadDisplayWithLane 클래스와 같이 차선 표시 기능과 교통량 표시 기능을 가지는 RoadDisplay의 하위 클래스 RoadDisplayWithLaneTraffic클래스를 추가하는 것이 적절할 수 도 있다. 하지만 다양한 기능의 조합을 고려해야 하는 경우 상속을 통한 기능의 확장은 각 기능별로 클래스를 추가해야 하는 단점이 있다. 차선 표시 기능, 교통량 표시 기능, 교차로 표시 기능이 있고 이들을 조합할 시 최대 7가지의 RoadDisplay 하위 클래스를 추가해야 한다. 이에 대한 해결책으로 데코레이터 패턴을 사용하면 된다.

 

 

- 해결책


public abstract 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(); } private void drawLane(){ 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 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 roadWithLaneTraffic = new TrafficDecorator(new LaneDecorator(new RoadDisplay()));
        roadWithLaneTraffic.draw();     //기본 도로 표시 + 차선 표시 + 교통량 표시
   }
}

위와 같이 각 추가 기능을 Decorator 클래스로 정의한 후 필요한 Decorator 객체를 조합함으로서 추가 기능의 조합을 구현했다.

'자바 > 디자인패턴' 카테고리의 다른 글

퍼사드 패턴  (0) 2017.06.08
프로토타입 패턴  (0) 2017.06.08
컴퍼지트 패턴  (0) 2017.06.07
옵저버(Observer) 패턴(2) - 직접 구현  (0) 2017.06.06
옵저버(Observer) 패턴(1) - JDK API 활용  (0) 2017.06.06

+ Recent posts