전략 패턴

정선호·2023년 5월 6일
0

Design Patterns

목록 보기
4/24

관련 영상
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~");
    }
}
profile
학습한 내용을 빠르게 다시 찾기 위한 저장소

0개의 댓글