상태 패턴과 비슷하지만, 전략패턴은 전략(상태)를 외부에서 전환한다
왜 쓰는가?
switch-case문으로 추가하게되면 아래에 case문이 계속 추가되면서 코드 길어지고 유지보수가 힘들어져서
또한 분기가 계속 증가할 경우에도 전략패턴은 상속을 하니까 하나만 써서 해결할 수 있다.
public enum eMonsterAction
{
Idle=1, AttackReady,Attack
}
public class Monster :Monobehavior
{
eMonsterAction actionType;
private start()
{
//무조건 공격상태라고 가정
actionType = eMonsterAction.Attack;
}
private IEnumerator MonsterActDo()
{
//어떤 행동인지 찾아서 그 행동을 수행한다
switch (actionType)
{
case eMonsterAction.Idle:
MonsterIdleState(this,action);
break;
case eMonsterAction.AttackReady:
MonsterAttackReadyState(this,action);
break;
case eMonsterAction.Attack:
MonsterAttackState(this, action);
break;
}
}
}
현재 case문을 보면 상태가 3개가 있는데 이것들은 하나의 매개변수를 받는 이름만 다른 메서드를 가지고있다
public abstract class MonsterStrategy
{
public abstract void MonsterActDo(Monster monster);
}
현재 case문을 보면 상태가 3개가 있기때문에 이것을 전부. 이것을 클래스로 바꿔준다
public class MonsterIdleStrategy : MonsterStrategy
{
public override void MonsterActDo(Monster monster)
{
//현재 아무것도안함. 추후 sprite이미지, sound, effect만 변경되면 될듯
}
}
public class MonsterAttackReadyStrategy : MonsterStrategy
{
public override void MonsterActDo(Monster monster)
{
//현재 아무것도안함. 추후 sprite이미지, sound, effect만 변경되면 될듯
}
}
public class MonsterAttackStrategy : MonsterStrategy
{
public override void MonsterActDo(Monster monster)
{
Debug.Log("몬스터 공격 상태");
}
}
둘중 아무거나 써도 상관없다. 익숙해질때까지는 3-1 방식이 나을듯
스위치-케이스문 안에서 전략패턴을 결정해서 사용
public enum eMonsterAction
{
Idle=1, AttackReady,Attack
}
public class Monster :Monobehavior
{
eMonsterAction actionType;
MonsterStrategy monsterStrategy;
private start()
{
//무조건 공격상태라고 가정
actionType = eMonsterAction.Attack;
}
private IEnumerator MonsterActDo()
{
//어떤 행동인지 찾아서 그 행동을 수행한다
switch (actionType)
{
case eMonsterAction.Idle:
monsterStrategy = new MonsterIdleStrategy(this,);
break;
case eMonsterAction.AttackReady:
monsterStrategy = new MonsterAttackReadyStrategy();
break;
case eMonsterAction.Attack:
monsterStrategy = new MonsterAttackStrategy();
break;
}
monsterStrategy.MonsterActDo(this); //전략에 따라 다른 메서드 실행
}
}
딕셔너리로 매번 new로 클래스를 생성해주지않아서 GC부담 줄이는 방식
public enum eMonsterAction
{
Idle=1, AttackReady,Attack
}
public class Monster :Monobehavior
{
eMonsterAction actionType;
MonsterStrategy monsterStrategy;
Dictionary<eMonsterAction, MonsterStrategy> monsterStrategyDic;
private start()
{
//무조건 공격상태라고 가정
actionType = eMonsterAction.Attack;
MakeMonsterStrategyDic();
}
public void MakeMonsterStrategyDic()
{
//foreach문 돌리며 모든 enum에 대해 딕셔너리키를 통해 전략을 설정
foreach(eMonsterAction type in Enum.GetValues(typeof(eMonsterAction)))
{
switch(type)
{
case eMonsterAction.Idle:
monsterStrategyDic[type] = new MonsterIdleStrategy();
break;
case eMonsterAction.AttackReady:
monsterStrategyDic[type] = new MonsterAttackReadyStrategy();
break;
case eMonsterAction.Attack:
monsterStrategyDic[type] = new MonsterAttackStrategy();
break;
}
}
}
private IEnumerator MonsterActDo()
{
//어떤 행동인지 찾아서 그 행동을 수행한다
monsterStrategyDic[actionType].MonsterActDo(this);
}
}