디자인 패턴

4. 데코레이터 패턴 (Decorator pattern)

EF DEV 2020. 12. 21. 23:23
주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴
- 위키백과 -

이번에 알아볼 패턴은 데코레이터 패턴이다.

이 패턴을 이용하면 정의와 마찬가지로 어떠한 객체에 기능을 중첩해가면서 객체를 꾸밀 수 있다.

 

아래 간단한 예제를 통해 알아보자.

 

public abstract class House
{
    public abstract void Introduce();
}

public class BaseHouse : House
{
    public override void Introduce()
    {
        Console.WriteLine("제 집을 소개합니다!");
    }
}

public abstract class HouseDecorator : House
{
    protected House house;
    public HouseDecorator(House house) => this.house = house;
}

public class HDBed : HouseDecorator
{
    public HDBed(House house) : base(house) { }

    public override void Introduce()
    {
        house.Introduce();
        Console.WriteLine("침대가 있어요!");
    }
}

public class HDComputer : HouseDecorator
{
    public HDComputer(House house) : base(house) { }

    public override void Introduce()
    {
        house.Introduce();
        Console.WriteLine("컴퓨터가 있어요!");
    }
}

public class HDPiano : HouseDecorator
{
    public HDPiano(House house) : base(house) { }

    public override void Introduce()
    {
        house.Introduce();
        Console.WriteLine("피아노가 있어요!");
    }
}

 

우선 House 라는 추상 클래스를 정의하여 꾸며갈 객체의 형태를 구성한다.

BaseHouse 에서는 이를 통해 기본이 되는 집을 구성하고,

HouseDecorator 에서는 실제 집을 꾸며줄 객체(데코레이터) 들의 상위 클래스를 구성한다.

 

이때 중요한 건 HouseDecorator 인데

이 클래스가 추상 클래스인 이유는 House 의 추상 메소드인 Introduce 를 여기서 구현할 필요가 없기 때문이다.

 

또한 최상위 클래스인 House 를 생성자에서 매개변수로 받아 멤버 변수인 house 값을 초기화하여

하위 클래스에서도 이를 이어받아 해당 값을 무조건 초기화할 수 있게 한다.

 

이 값은 앞서 설명한 기능을 중첩하기 위해 이전 객체저장하기 위함이다.

 

 

데코레이터 패턴의 구조는 위 모습과 같이 객체가 중첩되어 감싸진 형태라고 볼 수 있다.

 

실제로 사용한다면 아래와 같은 형태일 것이다.

 

// 방법 1
House house1 = new HDPiano(new HDComputer(new HDBed(new BaseHouse())));
house1.Introduce();

// 방법 2
House house2 = new BaseHouse();
house2 = new HDComputer(house2);
house2 = new HDPiano(house2);
house2.Introduce();

이제 패턴을 정리하며 마무리해보겠다.

 

  • 목적 : 객체중첩해가며 다양한 기능을 캡슐화하여 적용할 수 있다.
  • 방법 : 꾸미고자 하는 객체를 데코레이터로 기능을 중첩해가며 감싼다.
  • 주의점 : 위 사용 시 코드에서 볼 수 있듯 데코레이터의 수클래스 명칭에 따라서
                 다소 보기 불편할 수 있으므로 유의하며 사용해야 한다.

어느 정도 개발 경험이 있는 사람이라면 빌드 패턴과 유사한 느낌을 받았을지도 모르겠다.

하지만 빌드 패턴은 객체를 생성하기 위한 패턴이고 (Get, Set 메소드 사용)

데코레이터 패턴은 객체를 확장하기 위한 패턴이므로 구현 목적이 다르다. (클래스 구현)