📕 4. 객체지향 디자인 패턴
유니티에서 사용하면 좋을 디자인 패턴만 명시한다.
📄 5. 행동 패턴
클래스와 객체간 서로 상호작용하는 방법이나 책임 분배 방법을 정의 하나의 객체로 수행할 수 없는작업을 여러 객체로 분해하면서 결합도를 낮출수 있음
3). State Pattern
ⓐ 특징
- "상태"를 객체화한 패턴이다. 이 상태라는것도 참조가능하다.
- 상태에 따라 객체의 행위 내용을 변경해주는 패턴
- 메인 캐릭터가 가질만한 상태를 생각해보자. jump, walk, run 등등..
이러한 상태를 손쉽게 switcing 하고 싶을떄. 제안하는 패턴이다.
- 메인 캐릭터가 가질만한 상태를 생각해보자. jump, walk, run 등등..
- 오토마타의 state machine와 관련이 깊다.
ⓑ 왜 쓰는가?
- if 조건절이 많을때 사용하면 유용하다.
- 객체의 상태에 따라 동일한 동작을 다르게 처리해야할떄,
1. Menu System : 메뉴 UI 2. 미니게임 3. 인트로 영상 4. Animatior : 실제 유니티의 animatior에 구현이 되어있다. 5. 몬스터의 AI 만들기
ⓒ 구성요소
- State :
- 상태 전이를 시키는 상태전이 함수(handle) 를 추상화하여 ConcreateState가 파생되도록
- ConcreateState
- State를 상속받고, 상태전이 함수(handle) 를 구체화 한다.
- 그리고 이 객체 자체가 상태 가된다.
- Context || Player
- Player는 State 객체를 포함하고 있다.
- player.state = new ConcreateState()를 통해
- 상태 (ConcreateState) 로 전이한다.
ⓓ 예시
📂신호등 State (C#)📂
namespace DesignPattern { enum Estate{ GREEN, YELLOW, RED} //enum I{} /* 다음은 안좋은 예시 public class TrraficLight { private State mState; public TrraficLight(State _s){ this.state = _s; } public State state {get; set;} public void Speak(State _s){ if(_s == GREEN){Console.WriteLine("green light");} else if(_s == RED){Console.WriteLine("red light");} } public void Wait(State _s){ Console.WriteLine("Wait.. the light changed"); if(_s == GREEN){Console.WriteLine("green light");} else if(_s == RED){Console.WriteLine("red light");} } } */ public class TrraficLight { private State mState; public State state {get; set;} public TrraficLight(State _s){ this.state = _s; } public void Speak(){ this.state.Speak(); } public void Wait(){ this.state.Wait(); } } public interface State { public void Speak(); public void Wait(TrraficLight _trraficLight); } public class GreenLight : State { public void Speak(){Console.WriteLine("green light");} public void Wait(TrraficLight _trraficLight){ _trraficLight.state = RedLight;//바뀌어질 상태 Console.WriteLine("wait.. the light changed"); } } public class RedLight : State { public void Speak(){Console.WriteLine("red light");} public void Wait(TrraficLight _trraficLight){ _trraficLight.state = GreenLight;//바뀌어질 상태 Console.WriteLine("wait.. the light changed"); } } //서로 상태 클래스는 서로 각각 상태클래스를 알고있다. }
📂서있기, 앉기, 걷기, 달리기 (C#)📂
using System; using System.Collections; using System.Collections.Generic; namespace DesignPattern { public class Player { public Player() { speed = 0; state = new StateStandUp(this); } public int speed { get; set; } public State state { get; set; } public void Talk(String _msg) { Console.WriteLine($"플레이어의 말 : {_msg}"); } } //플레이어에 대한 State 객체 작성 public abstract class State { protected Player player; public State(Player _player) { this.player = _player; } public abstract void StandUp(); public abstract void SitDown(); public abstract void Walk(); public abstract void Run(); public abstract String GetDescription(); //현재 상태 반환 } public class StateStandUp : State { public StateStandUp(Player _player) : base(_player) { } public override void StandUp() { player.Talk("언제 음직일꺼야?"); } public override void SitDown() { player.Talk("앉으니깐 좋다."); player.state = new StateSitDown(player); } public override void Walk() { player.speed = 5; player.state = new StateWalk(player); player.Talk("걷기 시작."); } public override void Run() { player.speed = 20; player.state = new StateRun(player); player.Talk("갑자기?? 존나뛰어."); } public override String GetDescription() { return "지금은 서있는 상태"; } } public class StateSitDown : State { public StateSitDown(Player _player) : base(_player) { } public override void StandUp() { player.state = new StateStandUp(player); player.Talk("일어나자."); } public override void SitDown() { player.Talk("쥐나겠다."); } public override void Walk() { player.speed = 1; player.state = new StateStandUp(player); player.Talk("어떻게 앉은상태에서 걷냐? 일단 서있자"); } public override void Run() { player.speed = 1; player.state = new StateStandUp(player); player.Talk("어떻게 앉은상태에서 뛰냐 일단 서있자"); } public override String GetDescription() { return "앉아있음"; } } public class StateWalk : State { public StateWalk(Player _player) : base(_player) { } public override void StandUp() { player.speed = 0; player.state = new StateStandUp(player); player.Talk("멈춰.."); } public override void SitDown() { player.speed = 0; player.state = new StateSitDown(player); player.Talk("걷다가 앉으면 넘어질 수 있다."); } public override void Walk() { player.Talk("난 걷는걸 좋아하지"); } public override void Run() { player.speed = 20; player.state = new StateRun(player); player.Talk("슬슬 뛴다."); } public override String GetDescription() { return "걷는 중"; } } public class StateRun : State { public StateRun(Player _player) : base(_player) { } public override void StandUp() { player.speed = 0; player.state = new StateStandUp(player); player.Talk("뛰다가 갑자기 멈춰?? 연골 나가요."); } public override void SitDown() { player.speed = 0; player.state = new StateSitDown(player); player.Talk("뛰다가 어떻게 앉노.. 미쳤나"); } public override void Walk() { player.speed = 5; player.state = new StateWalk(player); player.Talk("속도 줄인다~"); } public override void Run() { player.speed += 2; player.state = new StateRun(player); player.Talk("더 빨리 뛰라고? ㅇㅋ"); } public override String GetDescription() { return "달리는 중"; } } static void StateMain() { Console.WriteLine("[1] : 서있기 | [2] : 앉기 | [3] : 걷기 | [4] : 뛰기 | [5] : 상태 출력 | [0] : 종료"); Player player = new Player(); bool stop = false; while (!stop) { var Input = Console.ReadLine(); try { var validValue = Input; } catch { Console.WriteLine("You did not enter a valid format."); Console.ReadLine(); } switch (Input) { case "1": player.state.StandUp(); break; case "2": player.state.SitDown(); break; case "3": player.state.Walk(); break; case "4": player.state.Run(); break; case "5": Console.WriteLine(player.state.GetDescription()); break; case "0": Console.WriteLine("프로그램 종료"); stop = true; return; default: break; } } } }
📂자전거 타기 (C#)📂
namespace DesignPattern{ public enum Direction { Left = -1, Right = 1 } public interface IBikeState { void Handle(BikeController bikeController); } public class BikeStateContext { public IBikeState currentState {get; set;} private readonly BikeController mBikeController; public BikeStateContext(BikeController _bikeController){ this.mBikeController = _bikeController; } public void Transition(IBikeState _state){ currentState = _state; currentState.Handle(mBikeController); } } /*BikeController.cs*/ public class BikeController : MonoBehaviour { [field : SerializeField] public float maxSpeed {get; private set;} = 2.0f; [field : SerializeField] public float turnDistance {get; private set;} = 2.0f; public float currentSpeed {get;set;} public Direction currentTurnDirection {get; private set;} private IBikeState mStartState; private IBikeState mStopState; private IBikeState mTurntState; private BikeStateContext mBikeStateContext; private void Awake() { mBikeStateContext = new BikeStateContext(this); mStartState = gameobject.AddComponent<BikerStateState>(); mStopState = gameobject.AddComponent<BikerStopState>(); mTurntState = gameobject.AddComponent<BikerTurnState>(); mBikeStateContext.Transition(mStopState); } public void StartBike() { mBikeStateContext.Transition(mStartState); } public void StopBike() { mBikeStateContext.Transition(mStopState); } public void Turn(Direction direction) { urrentTurnDirection = direction; mBikeStateContext.Transition(mTurntState); } } /*ClientState.cs*/ public class ClientState : MonoBehaviour { private BikeController mBikeController; private void Awake(){ MonoBehaviour = GetComponent<BikeController>(); } private void OnGUI(){ if (GUILayout.Button("Start Bike")) { mBikeController.StartBike(); } if (GUILayout.Button("Turn Left")) { mBikeController.Turn(Direction.Left); } if (GUILayout.Button("Turn Right")) { mBikeController.Turn(Direction.Right); } if (GUILayout.Button("Stop Bike")) { mBikeController.StopBike(); } } } }
참고
'CS > SW 공학' 카테고리의 다른 글
| 니앙팽이 - IoC Container | 1 | 의존 역전 원칙 (Dependency Inversion Principle) (0) | 2023.12.05 |
---|---|
| 니앙팽이 - 객체지향(OOP) | 4-9 | 유용한 패턴들 - Subclass Sandbox, Event queue, Object Pool (0) | 2023.02.02 |
| 니앙팽이 - 객체지향(OOP) | 4-7 | 행동패턴 - Observer pattern (0) | 2023.02.02 |
| 니앙팽이 - 객체지향(OOP) | 4-6 | 행동패턴 - Command pattern (0) | 2023.02.02 |
| 니앙팽이 - 객체지향(OOP) | 4-5 | 구조패턴 - Flyweight pattern (0) | 2023.02.02 |