[ Pattern ] Observer Pattern(관찰자 패턴) in Unity C#

[ Programming Pattern 시리즈 ]
싱글턴 패턴 (Singleton Pattern) Link
컴포넌트 패턴 (Component Pattern) Link

커멘드 패턴 (Command Pattern) Link
관찰자 패턴 (Observer Pattern) Link
상태 패턴 (State Pattern) Link

GoF의 디자인 패턴 책을 보면 옵저버 패턴에 대해서 다음과 같이 정의한다.

“객체 사이에 일 대 다의 의존 관계를 정의 해두어, 어떤 객체의 상태가 변할 때 그 객체에 의존성을 가진 다른 객체들이 그 변화를 통지 받고 자동으로 업데이트될 수 있게 만듭니다.”

Observer Pattern은 게임에서 업적 시스템 같은 형태에 쓰면 유용하게 쓸 수 있다. 객체나 코드를 스파게티 코드처럼 더럽히자 않고 깔끔하게 Noti만 띄우는 형태로 유지할 수 있다. Readability는 물론 Decoupling(어떤 코드를 수정했을 때 다른 코드를 거의 바꾸지 않아도 됨)을 잘 하게 만들어 주기 때문에 작업 분담에도 매우 유용하다.

아래는, 실린더가 위로 올라가는 동작을 하게 되고, 특정 높이에 다다르면 관찰자(Observer)인 큐브에게 알림을 주어 큐브의 위치를 바꾸는 동작을 하는 코드이다.
%e1%84%89%e1%85%b3%e1%84%8f%e1%85%b3%e1%84%85%e1%85%b5%e1%86%ab%e1%84%89%e1%85%a3%e1%86%ba-2016-11-29-%e1%84%8b%e1%85%a9%e1%84%92%e1%85%ae-6-39-17
이를 Observer Patter을 사용해서 유니티에서 구현하면 아래와 같이 구현할 수 있다.
주체인 Subject는 실린더이고, CubeActor가 큐브를 움직이게 하는 관찰자(Observer)이다.

<CubeActor.cs>

 

<Observer.cs>

 

<Subject.cs>

 

Observer Pattern(옵져버 패턴)은 특정 코드를 다른 코드와 섞이거나 엮이지 않고 Decoupling 시킬 때 아주 많이 쓰인다. 가령 물리 엔진이 돌아가는 코드 내부에 저급한(?ㅎ) 게임 컨텐츠 호출 코드를 놓는 엘레강스하지 않은 상황을 피하고 싶을 때 이 Pattern은 긴요하게 쓰일 수 있다. (단, 위 코드는 AddObserver, RemoveObserver 호출 시에 Nofity()  루프가 돌고 있지 않은 것을 가정으로 한다. 이 Crash를 피하려면 Copy해서 iteration하는 방법 등을 추가해야 한다.)

그런데 GoF의 디자인 패턴 책은 94년도에 OOP가 한창 뜨고 있을 때 나온 책이다. 현재는 Observer 패턴이 언어 자체에 녹아 있는 경우가 많다. Unity 엔진의 C#에서는 Delegate를 이용하면 이와 비슷한 기능을 더 간단하게 구현할 수 있다.

<CubeActor.cs>

 

<Subject.cs>

 

동일한 동작을 하고, 내부 구조도 크게 다르지 않으며 더 간단하게 구현된다.

Observer Pattern의 단점이라면 단점인 것은 프로그램에서 코드가 어떻게 상호 작용하는지 눈에 들어오지 않는 것이다. 그래서 어쩔 수 없이 런타임 때에 디버그를 걸어서 확인하는 수밖에 없다. 그러므로 코드의 특성상 양쪽 상호 작용을 일상적으로 자주 확인해야 한다면 관찰자 패턴 대신 코드를 명시적으로 넣어주는 것이 더 나을 수 있다.

Github Link :
Observer Pattern Unity Project #1
Observer Pattern Unity Project #2 (Delegate Version)