유니티로 배우는 게임 디자인 패턴을 읽고 정리하는 레포지토리
싱글톤은 클래스에 인스턴스가 하나만 있도록 하면서 이 인스턴스에 대한 전역 접근이 가능한 디자인 패턴이다.
장점
- 이 인스턴스에 대한 전역 접근이 가능하다.
- 하나의 인스턴스만을 가지기 때문에 공유 자원을 관리할 때 유용하다. 동시 접근시 리소스의 일관성을 유지할 수 있다.
단점
- 단위테스트가 어려워진다.
- SOLID 법칙에 위배된다.
객체(Context)가 내부 상태(State)를 기반으로 움직일 수 있도록 하는 디자인 패턴이다.
Context : 내부 상태를 변경할 수 있도록 요청하는 인터페이스로 현재 상태(Current State)에 대한 포인터를 보유한다.
IState : 구체적인 상태를 클래스로 연결할 수 있도록 설정하는 인터페이스
 
장점
- 상태가 개체와 분리되어 있기 때문에 상태별 행동을 구현, 추가, 수정하기 편하다.
단점
- 상태간 관계를 정의하지 않아 가독성이 부족할 수 있다(따로 다이어그램을 만들면 좋을것 같다). 상태간 전환을 정의하기 복잡하다.
- 상태별 구현해야하기 때문에 클래스의 수가 많아진다.
- SOLID 법칙에 위배된다.
전역적으로 이벤트를 관리하며 특정한 전역 이벤트 목록을 이벤트버스가 관리한다.
- 이벤트 버스 : 게시자와 구독자의 중개자 역할로, 전역접근이 가능하다.
- 게시자 : 이벤트 버스에 선언한 특정 종류의 이벤트를 구독자에게 게시할 수 있다.
- 구독자 : 이벤트 버스를 통해 이벤트의 구독자로 자신을 등록한다.
이벤트 버스는 전역 접근이 가능하며 전역 이벤트를 다루기 때문에 어떤 객체든 게시자와 구독자가 될 수 있다.
 
장점
- 직접참조 대신 이벤트 버스를 통하기 때문에 익명성이 보장된다.
- 비동기적으로 이벤트가 발생했을때 확인이 가능하다.
단점
- 구독자가 누구인지, 게시자가 누구인지에 대한 익명성 때문에 디버깅, 유닛 테스트가 어렵다.
옵저버 패턴은 특정 범위에 종속되지만, 이벤트 버스는 전역이기 때문에 사용할 부분을 잘 판단해야 할 것 같다.
객체 행동을 캡슐화하여 재사용성과 확장성을 높이며 의존성을 낮출수 있다.
- Invoker : 명령을 실행하고, 명령들을 관리하는 객체
- Receiver : 명령을 받아서 수행할 객체
- Command : Receiver에서 캡슐화되어 생성된 객체로 Receiver에게 행동을 직접적으로 지시한다.
커맨드 패턴을 사용했을때의 절차는 다음과 같다.
Client -> Invoker -> Command -> Receiver
원래라면 Client가 Receiver에게 바로 접근하지만, 커맨드 패턴을 사용하면 두 객체간 의존성도 떨어지고, Receiver의 행동을 확장할때 별다른 수정이 필요없이 Command 객체를 생성하는식으로 확장성도 챙길 수 있다. 또한 Invoker가 큐에 Command들을 담고 특정 상황이나 일정한 주기별로 이를 실행할 경우에는 비동기 처리도 가능하며 Command의 관리도 가능하다.
 
사진에서는 Client가 Reciever에게 요청하지만, 실제로는 Invoker에게 요청한다.
장점
- 객체간 의존성을 낮출 수 있다.
- 재사용성과 확장성을 높일수 있다.
- 비동기 처리가 가능하다.
단점
- 복잡성 증가
- Receiver의 행동별로 클래스를 만들어야하기 때문에 클래스가 굉장히 많아진다.
- 2번과 비슷하게 간단한 행동도 클래스로 만들어야한다.
객체에 관찰자와 주체의 역할을 할당한다, 컴포넌트 간 연결을 완전히 제거하는 대신 느슨한 결합으로 만들어 준다. 관찰자(Observer) 객체가 주체(Subject) 객체에 구독하면 주체의 상태가 변화가 있을 시 구독자에게 이를 알리는 방식이다. 옵저버 패턴의 강점은 특히 일대다 관계에서 발휘된다.
- Observer : 주체에 구독, 제거하여 주체의 상태변화를 감지하고자 하는 객체
- Subject : 상태 변화시 자신에게 등록된 관찰자들에게 변화됐음을 알리는 객체
 
사진에서는 Client가 Reciever에게 요청하지만, 실제로는 Invoker에게 요청한다.
장점
- 주체에 필요한 만큼 관찰자를 추가할 수 있다. 런타임에도 유동적으로 변동가능하다.
- 옵저버 패턴의 주요 이점은 하나의 주체에 대해 다수의 관찰자 객체 간의 이벤트 처리를 할 수 있다는 점이다. 일대다 관계가 있는 객체 간의 이벤트 처리 시스템 구현 문제를 해결할 수 있다.
단점
- 관찰자들의 알림 순서를 보장받지 못한다. 둘 이상의 관찰자 객체가 하나의 주체 객체에 등록했을 때 두 객체가 특정 순서에 맞춰 작동해야 했을 때 기본 형태의 옵저버 패턴은 적당하지 않다.
- 주체는 관찰자에 대한 강한 참조를 갖기 때문에 분리 삭제를 정확히 하지 않으면 객체를 쓰지 않음에도 GC가 회수 하지 않을 수 있다.
상태를 자주 변경하고 변경 사항에 대응해야 하는 종속성이 많은 핵심 컴포넌트가 있다면 옵저버 패턴가 용이하다. 해당 엔티티와 알림을 받게 하는 매커니즘 간 관계를 정의할 수 있다.