데코레이터 패턴(Decorator Pattern)

데코레이터 패턴(Decorator Pattern)이란?
데코레이터 패턴은 객체 지향 디자인 패턴 중 하나로, 기존의 객체에 새로운 기능을 동적으로 추가하기 위한 패턴입니다. 데코레이터 패턴을 사용하면, 기존 코드를 수정하지 않고도 객체의 책임과 역할을 확장할 수 있어 유연성이 높은 패턴입니다.

데코레이터 패턴의 구성요소
데코레이터 패턴은 다음과 같이 구성됩니다.

Component: 데코레이터 패턴에서 추가 기능을 부여할 객체의 인터페이스 역할을 합니다.
ConcreteComponent: Component 인터페이스를 구현한 구체적인 객체입니다.
Decorator: Component 인터페이스를 구현하고, 추가 기능을 부여할 객체의 추상 클래스입니다.
ConcreteDecorator: Decorator 클래스를 상속받아 실제로 추가 기능을 구현하는 구체적인 클래스입니다.


데코레이터 패턴 예제
예를 들어, Swift로 구현된 Coffee 클래스에 기능을 추가하고 싶다고 가정해봅시다. Coffee 클래스는 다음과 같이 정의될 수 있습니다.

protocol Coffee {
    var cost: Double { get }
    var description: String { get }
}

class SimpleCoffee: Coffee {
    var cost: Double {
        return 2.0
    }
    
    var description: String {
        return "Simple coffee"
    }
}

이제 Coffee 클래스에 데코레이터 패턴을 적용하여, 추가 기능을 부여하는 예제를 살펴보겠습니다.

class CoffeeDecorator: Coffee {
    let coffee: Coffee
    
    init(coffee: Coffee) {
        self.coffee = coffee
    }
    
    var cost: Double {
        return coffee.cost
    }
    
    var description: String {
        return coffee.description
    }
}

class Milk: CoffeeDecorator {
    override var cost: Double {
        return coffee.cost + 1.0
    }
    
    override var description: String {
        return coffee.description + ", milk"
    }
}

class Sugar: CoffeeDecorator {
    override var cost: Double {
        return coffee.cost + 0.5
    }
    
    override var description: String {
        return coffee.description + ", sugar"
    }
}

CoffeeDecorator 클래스는 Decorator 클래스의 역할을 합니다. 

Milk와 Sugar 클래스는 ConcreteDecorator 클래스의 역할을 합니다. 

이제, 위에서 정의한 클래스들을 사용하여, Coffee 객체에 기능을 추가해보겠습니다.

let simpleCoffee = SimpleCoffee()
print(simpleCoffee.description) // "Simple coffee"
print(simpleCoffee.cost) // 2.0

let coffeeWithMilk = Milk(coffee: simpleCoffee)
print(coffeeWithMilk.description) // "

let coffeeWithMilkAndSugar = Sugar(coffee: coffeeWithMilk)
print(coffeeWithMilkAndSugar.description) // "Simple coffee, milk, sugar"
print(coffeeWithMilkAndSugar.cost) // 3.5


위 예제에서는 SimpleCoffee 클래스를 Component 역할로 사용했습니다. 

CoffeeDecorator 클래스는 Decorator 클래스로 사용되며, ConcreteDecorator 역할을 하는 Milk와 Sugar 클래스가 있습니다.

Milk와 Sugar 클래스는 CoffeeDecorator 클래스를 상속받아, 기존에 없던 새로운 기능인 우유 추가와 설탕 추가를 구현합니다. 

이렇게 구현된 Milk와 Sugar 클래스를 사용하여, 기존 SimpleCoffee 객체에 새로운 기능을 추가할 수 있습니다.

데코레이터 패턴의 장점

데코레이터 패턴은 다음과 같은 장점이 있습니다.

1. 객체의 책임과 역할을 동적으로 확장할 수 있습니다.
2. 기존 코드를 수정하지 않아도 새로운 기능을 추가할 수 있습니다.
3. 단일 책임 원칙을 지키면서도 유연성을 확보할 수 있습니다.

데코레이터 패턴의 단점

데코레이터 패턴은 다음과 같은 단점이 있습니다.

1. 많은 클래스가 생성됩니다.
2. 객체 생성 순서가 중요합니다.
3. 객체의 깊은 복사가 어렵습니다.

마무리

데코레이터 패턴은 기존 코드를 수정하지 않고도 객체에 새로운 기능을 추가할 수 있어 유연성이 높은 패턴입니다. 

하지만 많은 클래스를 생성하고, 객체 생성 순서와 깊은 복사 문제가 있으므로 주의하여 사용해야 합니다.

 

감사합니다.