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

[C#/Unity][디자인패턴] 전략 패턴(Strategy Pattern)

by 스테디코디스트 2023. 12. 28.
반응형

1. 전략 패턴이란?

- 정책 패턴(Policy Pattern)이라고도 불리며 특정 알고리즘을 별도로 분리하여 설계하는 방법을 말함.

- 알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 사용할 수 있게 해줌.

- 실행 중에 알고리즘(전략)을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴.

- 객체의 행위를 변경하고 싶을 때, 직접 수정하지 않고 전략이라 불리는 캡슐화된 알고리즘을 변경.

- 특정한 계열의 알고리즘들을 정의하고, 각 알고리즘을 캡슐화하며, 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하도록 만든다.

- 객체들이 할 수 있는 각각의 행위에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화하는 인터페이스를 정의하여 객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법.

- 전략이란 일종의 알고리즘이 될 수도 있고, 기능이나 동작이 될 수도 있는 특정한 목표를 수행하기 위한 행동계획을 뜻함.

 

2. 전략 패턴을 사용하는 경우

- 어떤 일을 수행하는 알고리즘이 여러가지일 경우, 동작들을 미리 전략으로 정의함으로써 손쉽게 전략을 교체할 수 있는 알고리즘 변형이 빈번하게 필요한 경우에 사용된다.

- 한 알고리즘의 다양한 변형들을 사용하고 싶은 경우

- 런타임 중에 한 알고리즘에서 다른 알고리즘으로 전환하고 싶은 경우

- 알고리즘의 다른 변형들 사이를 전환하는 거대한 조건문이 클래스 내에 있는 경우

 

3. 전략 패턴의 장점

- 런타임에 한 객체 내부에서 사용되는 알고리즘들을 교환할 수 있다.

- 알고리즘을 사용하는 코드에서 알고리즘의 세부 구현 정보들을 고립할 수 있다.

- 상속을 합성으로 대체할 수 있다.

- 내용을 변경하지 않고 새로운 전략들을 도입할 수 있다.(개방 폐쇄 원칙)

- 캡슐화된 알고리즘을 사용하므로 재사용성이 좋다.

- 알고리즘 추가 및 수정에서 코드 수정이 최소화되므로 확장성이 높다.

 

4. 전략 패턴의 단점

- 알고리즘이 거의 변하지 않고, 몇 개 밖에 되지 않는다면 패턴 사용이 지나치게 복잡할 수 있음.

- 클라이언트들이 적절한 전략 선택을 위해 각 전략들 간의 차이점을 알고 있어야 함.

- 런타임 시에 알고리즘을 선택하는 데 추가적인 오버헤드가 발생할 수 있음.

- 알고리즘이 많아질수록 관리해야할 객체의 수가 늘어남.

 

5. 코드 구현

1) 구조

- Strategy Interface

:  모든 전략 구현체에 대한 공용 인터페이스

- Concrete Strategy

: 전략 알고리즘 객체들

: 알고리즘, 행위, 동작을 객체로 정의한 구현체

- Context 

: 알고리즘을 실행해야 할 때마다 해당 알고리즘과 연결된 전략 객체의 메소드를 호출

- Client

: 특정 전략 객체를 Context에 전달함으로써 전략을 등록하거나 변경하여 전략 알고리즘을 실행

 

2) 소스코드(C#)

- 패턴 적용 전

using System;

namespace StudyCSharp
{
    class Magic
    {
        public enum MagicType
        {
            Fire,    // 불
            Ice,     // 얼음
            Wind,    // 바람
        }

        public MagicType magicType;

        public void setMagic(MagicType type)
        {
            Console.Write(type + " Magic -> ");
            this.magicType = type;
        }

        public void Attack()
        {
            switch (magicType)
            {
                case MagicType.Fire:
                    Console.WriteLine("불 마법 사용");
                    Console.WriteLine();
                    break;
                case MagicType.Ice:
                    Console.WriteLine("얼음 마법 사용");
                    Console.WriteLine();
                    break;
                case MagicType.Wind:
                    Console.WriteLine("바람 마법 사용");
                    Console.WriteLine();
                    break;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Magic magic = new Magic();

            // 불 마법 전략 설정
            magic.setMagic(Magic.MagicType.Fire);
            magic.Attack();

            // 얼음 마법 전략 설정
            magic.setMagic(Magic.MagicType.Ice);
            magic.Attack();

            // 바람 마법 전략 설정
            magic.setMagic(Magic.MagicType.Wind);
            magic.Attack();
        }
    }
}

 

- 실행 결과

 

- 패턴 적용 후

using System;

namespace StudyCSharp
{
    // Strategy Interface
    interface Magic
    {
        string Name { get; }

        void Attack();
    }

    // Concrete Strategy 1
    class FireMagic : Magic
    {
        string name = "Fire Magic";
        public string Name { get => name; }

        public void Attack()
        {
            Console.WriteLine("불 마법 사용");
            Console.WriteLine();
        }
    }

    // Concrete Strategy 2
    class IceMagic : Magic
    {
        string name = "Ice Magic";
        public string Name { get => name; }

        public void Attack()
        {
            Console.WriteLine("얼음 마법 사용");
            Console.WriteLine();
        }
    }

    // Concrete Strategy 3
    class WindMagic : Magic
    {
        string name = "Wind Magic";
        public string Name { get => name; }

        public void Attack()
        {
            Console.WriteLine("바람 마법 사용");
            Console.WriteLine();
        }
    }

    // Context
    class MagicStrategy
    {
        Magic _magic;

        public void setMagic(Magic magic)
        {
            Console.Write(magic.Name + " -> ");
            this._magic = magic;
        }

        public void Attack()
        {
            _magic.Attack();
        }
    }

    // Client
    class Program
    {
        static void Main(string[] args)
        {
            // 마법 발동 무기 = 지팡이(완드)
            MagicStrategy wand = new MagicStrategy();

            // 불 마법 전략 설정
            wand.setMagic(new FireMagic());
            wand.Attack();

            // 얼음 마법 전략 설정
            wand.setMagic(new IceMagic());
            wand.Attack();

            // 바람 마법 전략 설정
            wand.setMagic(new WindMagic());
            wand.Attack();
        }
    }
}

 

- 실행 결과


<참고 사이트>

 

💠 전략(Strategy) 패턴 - 완벽 마스터하기

Strategy Pattern 전략 패턴은 실행(런타임) 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴 이다. 여기서 '전략'이란 일종의 알고리즘이 될 수

inpa.tistory.com

 

전략 패턴

/ 디자인 패턴들 / 행동 패턴 전략 패턴 다음 이름으로도 불립니다: Strategy 의도 전략 패턴은 알고리즘들의 패밀리를 정의하고, 각 패밀리를 별도의 클래스에 넣은 후 그들의 객체들을 상호교환

refactoring.guru

 

Strategy Pattern(전략 패턴)이란?

🚀 전략 패턴이란? 정책 패턴(Policy Pattern)이라고도 불림 알고리즘군을 정의하고 캡슐화해서 각각의 알고리즘군을 수정해서 사용할 수 있게 해줌 객체의 행위를 변경하고 싶은 경우 직접 수정하

ssdragon.tistory.com

 

전략 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 전략 패턴(strategy pattern) 또는 정책 패턴(policy pattern)은 실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다. 전략 패턴은 특정한 계열

ko.wikipedia.org