본문 바로가기
Study/디자인 패턴

[C#/Unity][디자인패턴] 데코레이터 패턴(Decorator Pattern)

by 스테디코디스트 2023. 11. 29.
반응형

1. 데코레이터 패턴이란?

- Decorate의 의미 '꾸민다'의 뜻 그대로 어떤 객체를 꾸며주기 위해 필요한 여러 요소들을 추가해주는 패턴.

- 객체에 추가 요소를 동적으로 더할 수 있는 디자인 패턴.

- 개발 확장에 있어 base 클래스 밑에 서브 클래스를 만들어 확장시킬 때, 데코레이터 패턴을 사용하면 서브 클래스를 만들어 확장할 때보다 더 확장성 있게 구현할 수 있음.

- 기본 기능에 추가할 수 있는 많은 종류의 부가 기능에서 파생되는 다양한 조합을 동적으로 구현할 수 있는 패턴.

- 객체의 결합을 통해 기능을 동적으로 유연하게 확장할 수 있도록 해주는 패턴.

- 각각이 개별적인 객체면서 parent에선 멤버인 child 객체를 사용할 수 있고, 관련 기능들을 위임하여 실행하는 패턴.

- OCP 원칙에 따라 구성된 패턴.

cf) OCP(Open-Closed Principle) 원칙 : 클래스는 확장에는 열려 있어야 하지만 변경에는 닫혀 있어야 한다.

 

2. 데코레이터 패턴을 사용하는 경우

- 객체의 기능을 동적으로 확장하고자 할 때 사용

- 상속받을 클래스가 상속이 불가능 할 때 사용

- 일시적 공격력 강화, 아이템을 먹는 경우 등 이에 해당

 

3. 데코레이터 패턴의 장점

1) 확장성 : 객체의 결합을 통해 자식 클래스를 만들지 않고도 객체의 기능을 동적으로 유연하게 확장할 수 있음.

2) 보존성 : 기존 코드를 수정하기 않고 객체를 여러 데코레이터로 래핑하여 합성할 수 있음.

3) 단일 책임 원칙 : 다양한 행동들의 여러 변형들을 구현하는 모놀리식 클래스를 여러 개의 작은 클래스들로 나눌 수 있음.

 

4. 데코레이터 패턴의 단점

1) 코드의 양과 스크립트의 양이 증가한다.

2) 래퍼들의 스택에서 특정 래퍼를 제거하기가 어렵다.

3) 클래스의 종류가 많아지고 객체를 파악하기 어려워진다.

4) 데코레이터의 행동이 데코레이터 스택 내의 순서에 의존하지 않는 방식으로 데코레이터를 구현하기가 어렵다.

 

5. 코드 구현

1) 최상위 추상 클래스 Skill을 상속받아 MagicBall 클래스와 Shield 클래스를 각각 구현

2) 최상위 추상 클래스 Skill을 상속받는 추상 클래스 Decorator 클래스도 있음.

3) Decorator 클래스를 상속받는 FireProperty 클래스, ElectricProperty 클래스를 각각 구현.

 

결론 : Decorator를 이용해 구현한 클래스들을 원하는 대로 MagicBall이나 Shield 클래스 래핑하여 쓸 수 있음.

 

- 다이어그램

 

- 소스 코드(c#)

using System;
using System.Collections.Generic;

namespace StudyCSharp
{
    // 최상위 추상 클래스
    public abstract class Skill
    {
        // 멤버변수
        protected string name; 
        protected float damage; 

        // 추상 메소드(객체와 데코레이터에서 구현)
        public abstract string GetName();
        public abstract float GetDamage();

        public abstract void GetInfo();
    }

    // 데코레이터 클래스
    public abstract class Decorator : Skill 
    {
        protected Skill skill;
    }

    // 꾸며질 객체 1 - 마법 구
    public class MagicBall : Skill 
    {
        public MagicBall() 
        {
            this.name = "볼";
            this.damage = 10f;
        }

        public override string GetName()
        {
            return this.name;
        }

        public override float GetDamage()
        {            
            return this.damage;
        }

        public override void GetInfo()
        {
            Console.WriteLine("스킬 명\t: " + this.name);
            Console.WriteLine("데미지\t: " + this.damage);
            Console.WriteLine();
        }
    }

    // 꾸며질 객체 2 - 실드
    public class Shield : Skill
    {
        public Shield()
        {
            this.name = "실드";
            this.damage = 0f;
        }

        public override string GetName()
        {
            return this.name;
        }

        public override float GetDamage()
        {
            return this.damage;
        }

        public override void GetInfo()
        {
            Console.WriteLine("스킬 명\t: " + this.name);
            Console.WriteLine("데미지\t: " + this.damage);
            Console.WriteLine();
        }
    }

    // 불 특성 부여
    public class FireProperty : Decorator
    {
        public FireProperty(Skill _skill)
        {
            this.skill = _skill;
            this.name = "파이어 " + _skill.GetName();
            this.damage = 3 + _skill.GetDamage();
        }

        public override string GetName()
        {
            return this.name;
        }

        public override float GetDamage()
        {
            return this.damage;
        }

        public override void GetInfo()
        {
            Console.WriteLine("스킬 명\t: " + this.name);
            Console.WriteLine("데미지\t: " + this.damage);
            Console.WriteLine();
        }
    }

    // 전기 특성 부여
    public class ElectricProperty : Decorator
    {
        public ElectricProperty(Skill _skill)
        {
            this.skill = _skill;
            this.name = "일렉트릭 " + _skill.GetName();
            this.damage = 5 + _skill.GetDamage();
        }

        public override string GetName()
        {
            return this.name;
        }

        public override float GetDamage()
        {
            return this.damage;
        }

        public override void GetInfo()
        {
            Console.WriteLine("스킬 명\t: " + this.name);
            Console.WriteLine("데미지\t: " + this.damage);
            Console.WriteLine();
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            // 일반 마법
            Skill magic_1 = new MagicBall();
            magic_1.GetInfo();

            // 파이어 볼
            Skill magic_2 = new FireProperty(new MagicBall());
            magic_2.GetInfo();

            // 일렉트릭 볼
            Skill magic_3 = new ElectricProperty(new MagicBall());
            magic_3.GetInfo();

            // 혼종 : 일렉트릭 파이어 볼
            Skill magic_4 = new ElectricProperty(new FireProperty(new MagicBall()));
            magic_4.GetInfo();

            Console.WriteLine("-----------------------------------\n");           

            // 일반 실드
            Skill shield_1 = new Shield();
            shield_1.GetInfo();

            // 파이어 실드
            Skill shield_2 = new FireProperty(new Shield());
            shield_2.GetInfo();

            // 일렉트릭 실드
            Skill shield_3 = new ElectricProperty(new Shield());
            shield_3.GetInfo();

            // 혼종 : 일렉트릭 파이어 실드
            Skill shield_4 = new ElectricProperty(new FireProperty(new Shield()));
            shield_4.GetInfo();
        }
    }
}

 

- 실행 결과


<참고 사이트>

 

Design Pattern: Decorator

Decorator pattern은 객체의 기능을 동적으로 확장하고자 할 때, 또는 상속받을 클래스가 상속이 불가능할 때 사용되는 디자인 패턴이다. 게임의 예를 들면 맵을 돌아다니다가 일시적으로 공격력이

batmask.net

 

데코레이터 패턴

/ 디자인 패턴들 / 구조 패턴 데코레이터 패턴 다음 이름으로도 불립니다: 래퍼(Wrapper), Decorator 의도 데코레이터는 객체들을 새로운 행동들을 포함한 특수 래퍼 객체들 내에 넣어서 위 행동들을

refactoring.guru

 

 

 

[Unity] 디자인 패턴 : 데코레이터 패턴(Decorator Pattern)

Unity와 C#을 통한 데코레이터 패턴(Decorator Pattern)의 정의와 사용 방법에 대해 알아보자. 1. 데코레이터 패턴(Decorator Pattern)이란? 데코레이터 패턴(Decorator Pattern)은 객체에 추가 요소를 동적으로 더

wonjuri.tistory.com

 

 

[디자인패턴] 7. 유니티에서 데코레이터 패턴

오늘의 디자인 패턴은 데코레이터 패턴입니다. 데코레이터 패턴의 정의는 객체에 추가적인 요건을 동적으로 첨가한다는 것입니다. 그리고 서브클래스를 만드는 것을 통해서 기능을 유연하게

welcomeheesuk.tistory.com

 

 

[C#] Decorator Pattern

Decorator Pattern 데코레이터 패턴이란 객체의 결합을 통해 기능을 동적으로 유연하게 확장 할 수 있도록 해주는 패턴이다. 즉, 기본 기능에 추가할 수 있는 기능의 종류가 많은 경우에 각 추가 기능

junco.tistory.com

 

 

[C# 디자인패턴] 제10강 데코레이터패턴

예제 코드 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.

codepump.tistory.com