본문 바로가기
컴퓨터 과학/디자인패턴

[디자인패턴] 구조 패턴(6) : 데코레이터(Decorator)

by webcodur 2024. 3. 25.
728x90

목차

     

    데코레이터(Decorator)

    데코레이터 디자인 패턴은 객체의 수정 가능한 행위를 동적으로 확장할 수 있는 구조적 디자인 패턴이다. 기본적으로 이 패턴은 객체에 추가적인 책임이나 행위를 런타임에 첨가하는 것을 가능하게 한다. 이 패턴의 이름은 '장식'이라는 뜻의 '데코레이터'에서 유래했다. 소프트웨어 개발에서 이 패턴을 사용함으로써 기존 코드를 수정하지 않고도 객체의 기능을 유연하게 확장할 수 있다.

     

    패턴 미적용 예시

    게임에서 캐릭터의 무기 업그레이드를 하는 경우를 생각해 보자. 다음 예시에서는 새로운 속성을 추가할 때마다 별도의 클래스를 생성해야 하며, 다양한 속성의 조합을 지원하기 위해서는 클래스의 수가 기하급수적으로 늘어난다.

    // 기본 무기 클래스
    class BasicWeapon {
        public virtual string Attack() {
            return "공격한다";
        }
    }
    
    // 무기를 업그레이드하는 클래스들이 별도로 존재
    // 예를 들어, 불꽃 속성을 추가하는 클래스
    class FireWeapon {
        BasicWeapon weapon;
    
        public FireWeapon(BasicWeapon weapon) {
            this.weapon = weapon;
        }
    
        public string Attack() {
            return weapon.Attack() + ", 불꽃 속성 공격을 추가한다";
        }
    }
    
    // 사용 예
    BasicWeapon weapon = new BasicWeapon();
    FireWeapon fireWeapon = new FireWeapon(weapon);
    Console.WriteLine(fireWeapon.Attack());
    

     

     

     

    패턴 적용 예시

    데코레이터 패턴의 구성 요소

    1. Component: 기본 기능을 정의하는 인터페이스
    2. ConcreteComponent: Component 인터페이스를 구현하며, 기본 기능을 제공하는 클래스
    3. Decorator: Component 인터페이스를 구현하며, 추가 기능을 제공하기 위해 다른 Component 객체를 감싸는 클래스
    4. ConcreteDecorator: Decorator 클래스를 상속받아 추가적인 기능을 실제로 구현하는 클래스
    // Component
    interface IWeapon {
        string Attack();
    }
    
    // ConcreteComponent
    class BasicWeapon : IWeapon {
        public virtual string Attack() {
            return "공격한다";
        }
    }
    
    // Decorator
    abstract class WeaponDecorator : IWeapon {
        protected IWeapon decoratedWeapon;
    
        public WeaponDecorator(IWeapon weapon) {
            this.decoratedWeapon = weapon;
        }
    
        public virtual string Attack() {
            return decoratedWeapon.Attack();
        }
    }
    
    // ConcreteDecorator
    class FireWeaponDecorator : WeaponDecorator {
        public FireWeaponDecorator(IWeapon weapon) : base(weapon) {}
    
        public override string Attack() {
            return base.Attack() + ", 불꽃 속성 공격을 추가한다";
        }
    }
    
    // 사용 예
    IWeapon weapon = new BasicWeapon();
    weapon = new FireWeaponDecorator(weapon);
    Console.WriteLine(weapon.Attack());
    

     

    이 방식을 사용하면 무기에 여러 가지 속성을 유연하게 추가할 수 있다. 예를 들어, 불꽃 속성 외에도 얼음 속성이나 전기 속성 등 다양한 속성을 추가하는 것이 가능하다. 또한, 이러한 속성들을 조합하여 사용할 수도 있다는 장점이 있다.