본문 바로가기

Design Patterns

Observer Pattern ② 패턴 활용 예제

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
먼저 지난 Strategy Pattern 예제는 스타크래프트로 만들었는데 이번에는 월드 오브 워크래프트를 이용해서 한번 만들어 보았습니다. 게임을 통해서 무언가 공부를 한다는건 재미있고 또 이해하는데 많은 도움이 되는것 같습니다.

먼저 옵저버 패턴에서의 Subject(주제)가 되는 것은 몬스터라고 설정을 했습니다. 몬스터를 잡기 위해서는 혼자보다는 파티 구성을 해서 잡기 때문에 파티원 하나하나를 옵저버로 보고, 몬스터의 광포화 상태와 약점의 속성이 바뀔때 마다 플레이어의 반응이 달라지도록 구현을 했습니다.

일단 몬스터라는 클래스의 소스코드를 살펴보시겠습니다.

열거형(Enum) 클래스를 사용하여 약점을 정의했고, 출력해주기 위한 한글화된 약점들을 매개변수로 가지고 있습니다. 기본적인 멤버 변수는 몬스터의 이름과 약점 몬스터와 전투를 벌이는(몬스터의 상태변화를 알아가는) 플레이어 목록을 나타내는 자료구조, 몬스터가 광포화에 빠졌는지 안빠졌는지를 나타내는 불린형 변수, 총 4가지가 있습니다.

중요한 메소드로는 옵저버 패턴을 적용하기위해 인터페이스로 사용했던 Dungeon에서 정의했던 플레이어(옵저버)를 등록하고, 제거하거나, 등록된 플레이어에게 몬스터의 상태를 알리는 메소드가 있습니다. 기본적으로 몬스터의 상태가 변하게 되면, 몬스터의 상태변화를 출력해줌과 동시에 등록된 플레이어 객체에게 상태가 변했다는 것을 알려주고, 플레이어가 가지고 있던 몬스터의 상태 변화를 업데이트 해줍니다.


사용자 삽입 이미지

위와 같은 다이어그램이 그려지게 됩니다. 기존의 Observer Pattern의 개념을 설명하기 위한 다이어그램과 크게 차이가 있지 않습니다. 약간의 차이점이라고 한다면 첫째로, Reactionable 라는 인터페이스는 모든 직업마다, 몬스터의 상태에 따라서 reaction() 이라는 메소드를 구현하게 끔 해주었으며, 실제로 상태에 따라서 행동이 달라지게 됩니다.

여기서 Subject는 몬스터가 되고, Observer들은 플레이어인 Warrior, Hunter, Priest, Warlock, Wizard라는 클래스가 됩니다. 따라서 몬스터의 상태가 변하는 setStatus() 메소드가 호출이 되면, 몬스터의 상태가 변하게 되며, 그에 따라 모든 플레이어에게 상태변화가 되었다고 update() 메소드를 호출하게 하는 형식입니다.

그럼 어떻게 상태 변화가 되는지 테스트를 통해서 알아보도록 하지요~

public class ObserverTest {

      public static void main(String[] args) {

            Monster monster = new Monster("크로마구스");

            Warrior warrior = new Warrior("전사", monster);

            Warlock warlock = new Warlock("흑마법사", monster);

            Hunter hunter = new Hunter("사냥꾼", monster);

            Wizard wizard = new Wizard("마법사", monster);

            Priest priest = new Priest("사제", monster);

            monster.setStatus(Weakness.FLAME, true);

            monster.setStatus(Weakness.FROST, false);

            monster.removePlayer(hunter);

            monster.setStatus(Weakness.NONE, true);

            monster.registerPlayer(hunter);

      }

}

이런 테스트 코드를 작성했습니다. 몬스터(Subject) 객체 생성해주시고 옵저버 객체 5마리 생성해주시고, 몬스터 객체의 옵저버로 등록을 해주십니다~ 상태변화를 세번 일으켰고, 사냥꾼을 옵저버에서 뺐다가 넣었다가 해봤습니다. 콘솔창을 통해서 반응을 살펴보도록 하겠습니다.
사용자 삽입 이미지
먼저 전투가 시작되는것을 알리고, 전투에 참여하는 플레이어(옵저버)들이 참여했다는 것을 알려줍니다.

상태 변화 별로 한번 보도록 할까요?

첫번째, 크로마구스(몬스터)가 광포화 상태에 빠지게 되고, 화염속성에 약점을 보이게 됩니다.

두번째, 광포화가 사라지도 냉기속성에 약점을 보이게 됩니다. 또한 사냥꾼이 전투 불능이 되었습니다.

세번째, 전투 불능된 사냥꾼은 몬스터의 정보를 받는 옵저버가 아니므로 상태에 따라서 반응하지 않습니다. 하지만 전투 불능이 아니었습니다. 사냥꾼은 죽은척하기를 사용하니까요! 그래서 다시 전투에 참여합니다.



광포화의 유무에 따라 행동이 변화하는 전사, 사제, 사냥꾼과 약점속성의 변화에 따라 행동이 바뀌는 흑마법사, 마법사의 행동들을 유심히 보시길 바랍니다.

몬스터의 상태가 변할때마다 각각의 직업을 가진 플레이어가 그 상황에 대한 정보를 업데이트 받고 또 그 상황에 알맞은 행동들을 하게 끔 하는것, 다시 말하면, Subject 객체의 상태가 변하면 이 상태 정보를 필요로 하는 옵저버들에게 상태 갱신을 하도록 하다는겁니다.

하지만 이게 옵저버 패턴의 전부가 아닙니다. 위와 같이 subject가 모든 Observer들에게 Broadcasting 해주는 방법을 push 방식이라고 합니다.

그럼 Pull 방법은 어떤 경우일까요? Pull방식의 경우에는 다르게 한번 알아보도록 하겠습니다!