장식자 패턴(Wrapper)

Groot·2023년 12월 10일
0

TIL

목록 보기
142/148
post-thumbnail

장식자 패턴(Wrapper)

  • 객체에 동적으로 새로운 책임을 추가할 수 있는 패턴, 기능 추가에서 서브클래싱 보다 융통성 있는 방법을 제공.
  • 객체들을 새로운 행동들을 포함한 특수 래퍼 객체들 내에 넣어서 위 행동들을 해당 객체들에 연결.

활용성

  • 다른 객체에 영향을 주지 않고 개개의 객체에 새로운 책임을 추가할 때 사용
  • 제거될 수 있는 책임에 대해 사용
  • 상속으로 서브클래스를 계속 만드는 방법이 적절하지 않을 때 사용.

구조

요소

  • 컴포넌트(Component)
    • 동적으로 추가할 서비스를 가질 가능성이 있는 객체들의 인터페이스
  • 구상 컴포넌트(ConcreteComponent)
    • 추가적인 서비스가 실제로 정의되어야 할 필요가 있는 객체
  • 데코레이터(Decorator)
    • 객체에 대한 참조자를 관리하면서 컴포넌트에 정의된 인터페이스를 만족하도록 인터페이스를 정의
  • 구상 데코레이터(ConcreteDecorator)
    • 컴포넌트에 새롭게 추가할 서비스를 실제로 구현

협력 방법

  • 데코레이터는 자신의 컴포넌트 객체쪽으로 요청을 전달.

장점

  • 단순한 상속보다 설계의 융통성 증대.
    • 런타임에 데코레이터를 객체와 연결하거나 분리하는 작업을 통해 새로운 책임을 추가하거나 삭제하는 일이 가능.
  • 상위 클래스에 많은 기능이 누적되는 상황을 피할 수 있다.
    • 필요한 기능만 개발하고 누락된 서비스들을 데코레이터 객체를 통해 지속적으로 추가 가능.
  • 단일 책임 원칙.
    • 다양한 행동들의 여러 변형들을 구현하는 모놀리식 클래스를 여러 개의 작은 클래스들로 나눌 수 있다.

단점

  • 래퍼들의 스택에서 특정 래퍼를 제거하기가 어렵다.
  • 데코레이터의 행동이 데코레이터 스택 내의 순서에 의존하지 않는 방식으로 데코레이터를 구현하기가 어렵다.
  • 계층들의 초기 설정 코드가 보기 흉할 수 있다.

예시 코드

참고

protocol Coffee {
    func cost() -> Double
    func description() -> String
}

class SimpleCoffee: Coffee {
    func cost() -> Double {
        return 2.0
    }
    
    func description() -> String {
        return "Simple Coffee"
    }
}

class MilkDecorator: Coffee {
    let coffee: Coffee
    
    init(coffee: Coffee) {
        self.coffee = coffee
    }
    
    func cost() -> Double {
        return coffee.cost() + 1.0
    }
    
    func description() -> String {
        return coffee.description() + ", Milk"
    }
}

class SugarDecorator: Coffee {
    let coffee: Coffee
    
    init(coffee: Coffee) {
        self.coffee = coffee
    }
    
    func cost() -> Double {
        return coffee.cost() + 0.5
    }
    
    func description() -> String {
        return coffee.description() + ", Sugar"
    }
}

var coffee: Coffee = SimpleCoffee()
print("Cost: \(coffee.cost()), Description: \(coffee.description())")

coffee = MilkDecorator(coffee: coffee)
print("Cost: \(coffee.cost()), Description: \(coffee.description())")

coffee = SugarDecorator(coffee: coffee)
print("Cost: \(coffee.cost()), Description: \(coffee.description())")
profile
I Am Groot

0개의 댓글