디자인패턴, OOP

데코레이터 패턴(Decorator Pattern)

TedDev 2024. 8. 14. 15:59
728x90

데코레이터 패턴(Decorator Pattern)은 객체 지향 디자인 패턴 중 하나로, 기존 객체에 새로운 기능을 동적으로 추가하거나 기존 기능을 변경할 수 있는 패턴이다. 이 패턴은 상속을 사용하지 않고도 객체의 기능을 확장할 수 있게 해주며, 컴포지션(Composition)을 활용해 유연한 구조를 제공한다.

 

 

 

데코레이터 패턴의 특징

  1. 동적 기능 확장 : 데코레이터 패턴은 객체를 감싸는(wrapper) 방식으로 기존 객체에 새로운 기능을 추가한다. 이렇게 함으로써 원래 객체의 코드를 변경하지 않고도 기능을 확장할 수 있다.
  2. 유연성 : 여러 데코레이터를 조합하여 객체의 기능을 점진적으로 확장할 수 있다. 이를 통해 객체의 기능을 필요에 따라 유연하게 구성할 수 있다.
  3. 대체 가능성 : 데코레이터는 원래 객체와 동일한 인터페이스를 구현하기 때문에, 원래 객체를 데코레이터로 대체하는 것이 가능하다. 이는 코드에서 원래 객체와 데코레이터 객체를 구분하지 않고 사용할 수 있게 해준다.

 

데코레이터 패턴 구조

데코레이터 패턴의 구조는 다음과 같다.

  1. 컴포넌트(Component) : 기능을 추가할 대상 객체의 인터페이스나 추상 클래스이다.
  2. 구체적인 컴포넌트(Concrete Component) : 기본적인 기능을 구현한 클래스이다.
  3. 데코레이터(Decorator) : Component를 확장하는 추상 클래스 또는 인터페이스로, 구체적인 컴포넌트를 감싸서 추가적인 기능을 제공하는 역할을 한다.
  4. 구체적인 데코레이터(Concrete Decorator) : 데코레이터의 구체적인 구현체로, 기존 기능에 새로운 기능을 추가한다.

 

예시

아래는 데코레이터 패턴을 사용해 커피에 다양한 첨가물을 추가하는 예시

// Component
interface Coffee {
    String getDescription();
    double getCost();
}

// Concrete Component
class SimpleCoffee implements Coffee {
    public String getDescription() {
        return "Simple Coffee";
    }

    public double getCost() {
        return 2.0;
    }
}

// Decorator
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

    public double getCost() {
        return decoratedCoffee.getCost();
    }
}

// Concrete Decorator 1
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return decoratedCoffee.getDescription() + ", Milk";
    }

    public double getCost() {
        return decoratedCoffee.getCost() + 0.5;
    }
}

// Concrete Decorator 2
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return decoratedCoffee.getDescription() + ", Sugar";
    }

    public double getCost() {
        return decoratedCoffee.getCost() + 0.2;
    }
}

// 사용 예시
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " $" + coffee.getCost());

coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " $" + coffee.getCost());

coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " $" + coffee.getCost());
  • SimpleCoffee 클래스는 기본 커피를 나타내며, MilkDecorator와 SugarDecorator는 각각 우유와 설탕을 추가하는 데코레이터
  • 각 데코레이터는 기존 커피 객체를 감싸며, getDescription()과 getCost() 메서드를 오버라이드하여 새로운 기능을 추가한다.
  • MilkDecorator와 SugarDecorator를 조합하여 커피에 우유와 설탕을 동적으로 추가할 수 있다.

 

정리

데코레이터 패턴은 객체에 동적으로 기능을 추가할 수 있는 강력한 도구이다. 이 패턴은 코드의 재사용성을 높이고, 새로운 기능을 추가할 때 기존 코드를 수정하지 않아도 되므로 유지보수성을 크게 향상시킨다. 또한, 여러 데코레이터를 조합하여 다양한 기능을 유연하게 적용할 수 있다는 점에서 객체 지향 프로그래밍에서 매우 유용하게 사용된다.

 

반응형