관련 영상
C# 전략 패턴 구현
전략 패턴
위키피디아-전략 패턴
설명 및 스도코드
- 전략 패턴(strategy pattern) 또는 정책 패턴(policy pattern)은 실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다. 전략 패턴은
- 특정한 계열의 알고리즘들을 정의하고
- 각 알고리즘을 캡슐화하며
- 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다.
- 특정 상황에 따라 행동을 바꾸고 싶을 때 적용하기 좋은 패턴이다.
- 오브젝트가 여러 상황에 따라 사용하는 전략(코드)가 달라질 때
- 상태 머신(전략 패턴을 유한 상태 머신처럼 확장할 수 있다)
- 여러 객체가 있고, 그 객체마다 행동이 다 다를 때
전략 패턴의 구조
- 콘텍스트(Context)
- 구상 전략 중 하나에 대한 참조를 유지하고 전략 인터페이스를 통해서만 해당 객체와 통신
- 알고리즘을 실행해야 할 때마다 연결된 전략 객체의 실행 메서드 호출
- 콘텍스트는 알고리즘이 어떻게 실행되는지와 자신이 어떤 유형의 전략과 함께 작동하는지 모름
- 전략 인터페이스(Strategy Interface)
- 모든 구상 전략에 공통이며 콘텍스트가 전략을 실행하는데 사용하는 메서드 선언
- 구상 전략(Concrete Strategy)
- 콘텍스트가 사용하는 알고리즘의 다양한 변형들을 구현
- 클라이언트
- 특정 전략 객체를 만들어 콘텍스트에 전달
- 콘텍스트는 클라이언트들이 런타임에 콘텍스트와 관련된 전략을 대체할 수 있도록 하는
setter
를 노출
전략 패턴의 장단점
- 장점
- 코드 중복 방지
- 런타임(Runtime)시에 타겟 메소드 변경
- 확장성(신규 클래스) 및 알고리즘 변경 용이
- 단점
- 어플리케이션에 들어가는 모든 전략을 알고 있어야 함
- 전략을 추상화한 인터페이스가 효율적이지 못할 수 있음
전략 패턴의 적용
- 전략 패턴은 객체 내에서 한 알고리즘의 다양한 변형들을 사용하고 싶을 때, 그리고 런타임 중에 한 알고리즘에서 다른 알고리즘으로 전환하고 싶을 때 사용
- 또 전략 패턴은 객체의 행동들을 특정 하위 행동들을 다양한 방식으로 수행할 수 있는 다른 하위 객체들과 연관시켜 객체의 행동들을 런타임에 간접적으로 변경할 수 있게 해줌.
- 전략 패턴은 일부 행동을 실행하는 방식에서만 차이가 있는 유사한 클래스들이 많은 경우에 사용
- 전략 패턴은 다양한 행동들을 별도의 클래스 계층구조로 추출하고 원래 클래스들을 하나로 결합하여 중복 코드를 줄일 수 있게 해줌.
- 전략 패턴을 사용하여 클래스의 비즈니스 로직을 해당 로직의 콘텍스트에서 그리 중요하지 않을지도 모르는 알고리즘들의 구현 세부 사항들로부터 고립
- 전략 패턴은 코드의 나머지 부분에서 해당 코드, 내부 데이터, 그리고 다양한 알고리즘들의 의존 관계들을 고립시킬 수 있다. 다양한 클라이언트들이 알고리즘들을 실행하고 런타임에 전환하기 위한 간단한 인터페이스를 얻는다
- 이 패턴은 같은 알고리즘의 다른 변형들 사이를 전환하는 거대한 조건문이 당신의 클래스에 있는 경우에 사용
- 전략 패턴을 사용하면 모든 알고리즘을 같은 인터페이스를 구현하는 별도의 클래스들로 추출하여 이러한 조건문을 제거할 수 있다. 원래 객체는 알고리즘의 모든 변형들을 구현하는 대신 이러한 객체들 중 하나에 실행을 위임
전략 패턴을 사용해 구현한 Unity 무기 시스템
- 무기 컨트롤러
- 플레이어 오브젝트가 소유하는 무기 컨트롤러
- 장착된 무기를 사용하면 그 무기의 효과를 불러온다.
- 아래 코드는
Update
문에 실행하였지만 상태 머신처럼 원하는 실행 상황을 조절하여 구현할 수 있다.
public class WeaponController : MonoBehaviour
{
public Weapon curWeapon;
public Weapon prevWeapon;
void Start()
{
/* 무기 변경시 */
// 이전 무기를 이전무기 칸에
prevWeapon = curWeapon;
// 현재 사용할 무기의 초기화
curWeapon.Init(data);
}
void Update()
{
if (prevWeapon != curWeapon)
{
curWeapon.Init();
prevWeapon = curWeapon;
}
// 무기 사용
curWeapon.Use();
}
- 무기 추상 클래스
- 플레이어가 사용할 무기들의 원형
- 구현부는 각각의 무기에 맞춰 구현
public abstract class Weapon
{
// 무기 클래스에 필요한 데이터
public Data data;
// 초기화 함수
public abstract void Init();
// 실행 함수
public abstract void Use();
}
전략 패턴을 사용한 자동차 종류 추가
- 기존의 자동차 클래스에서 날 수 있는 자동차를 전략 패턴을 이용해 추가하는 방법
- 특정 행동(여기서는 Fly)의 추가 요구사항이 들어오면 인터페이스를 상속받는 행동 클래스를 확장하여 재사용성이 높은 코드를 구현할 수 있음
- Fly 행동을 사용하는 Car 원형 클래스
public abstract class Car
{
// 특정 행동에 대한 인터페이스
IFlyBehaviour flyBehaviour;
// Car 클래스의 추상 함수
public abstract void Move();
public abstract void Display();
// 특정 행동을 실행하는 함수
public void StartFly() { flyBehaviour.Fly(); }
// 다른 행동 유형으로 변경하는 함수
public void SetFlyBehaviour(iFlyBehaviour newBehaviour)
{
flyBehaviour = newBehaviour;
}
- Fly 행동 인터페이스 및 구현부를 작성한 자식 클래스
public interface IFlyBehaviour
{
void Fly();
}
public class Flyable : MonoBehaviour, IFlyBehaviour
{
// 행동 구현 부분
public void Fly()
{
Debug Log("I can fly~");
}
}
public class FlyDisable : MonoBehaviour, IFlyBehaviour
{
// 행동 구현 부분
public void Fly()
{
Debug Log("I cannot fly~");
}
}