본문 바로가기
유니티 공부/Unity

Unity - 옵저버 패턴(Observer Pattern)

by 코딩하는 돼징 2023. 5. 21.
반응형

Observer Pattern이란?

1 : N 종속 관계를 구현하는데 사용되는 패턴이다. 한 객체의 상태 변경이 다른 여러 객체에게 알려지고 자동으로 업데이트 될때 사용된다. 예를 들어 유뷰트 채널은 발행자(Subject)이 되는거고 구독자들은 관찰자(Observer)가 되는구조로 보면 된다. 유튜버가 영상을 올리면 여러 명의 구독자들은 모두 영상의 알림이 간다. 하지만 구독을 취소한 경우에는 알림이 가지 않는다.

 

왜 필요할까?

서로의 정보를 주고 받는 객체들의 규모가 클수록 복잡성이 증가하게 되는데 이때 가이드라인을 제시해줄 수 있는 것이 옵저버패턴이다.

 

예를 들어 마음에 드는 집 매물이 나왔는지 확인하고 싶다고 가정해보자

01 옵저버 패턴을 사용하지 않는 경우

입주 희망자는 그러면 공인 중개사에 집 매물이 나올때까지 계속 전화를 해봐야 할 것이다.

https://www.youtube.com/watch?v=boXNtyeOzuc

02 옵저버 패턴을 사용하는 경우

입주 희망자가 공인중개사에 전화해서 방나오면 알려주세요라고 한 다음 굳이 또 연락을 할 필요가 없이 방이 나오게되면 공인중개사쪽에서 연락을 주는 방식이다.

https://www.youtube.com/watch?v=boXNtyeOzuc


옵저버 패턴 실제 구조

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%98%B5%EC%A0%80%EB%B2%84Observer-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

1. 구성요소

01 ISubject (주체)

관찰 대상자를 정의하는 인터페이스이다.

public interface ISubject
{
    void AddObs(IObserver observer); // Observer 등록
    void RemoveObs(IObserver observer); // Observer 제거
    void NotiftyObs(); // Observer들에게 상태 변경 알림
}

02 ConcreteSubject(구체적인 주체)

Subject의 역할은 관찰자인 Observer들을 내부 리스트에 등록/삭제하는 인프라를 가지고 있다. 그리고 상태를 변경하거나 어떤 동작을 실행할때, Observer들에게 알림을 발행한다.

public class ConcreteSubject : ISubject
{
    List<IObserver> observers = new List<IObserver>(); // Observer를 관리
    int information;

    public void AttachObs(IObserver observer)
    {
        observers.Add(observer);
    }

    public void DetachObs(IObserver observer)
    {
        observers.Remove(observer);
    }
    
    // Observer들에게 정보 전달
    public void NotifyObs()
    {
        foreach (IObserver observer in observers)
        {
            observer.Update(state);
        }
    }

    // 갱신된 정보
    public void SetState(int newInformation)
    {
        information = newInformation;
        NotifyObs();
    }
}

03 IObserver(관찰자)

관찰자는 주체의 상태 변경을 관찰하고 이에 대한 업데이트를 하는 객체이다. 관찰자는 주체에 등록되어 있으며, 주체로부터 상태 변경 알림을 받으면 자동으로 업데이트 된다.

public interface IObserver
{
    void Update(int newState); // 상태 Update 알림 함수
}

04 Observer(관찰자)

Observer들은 Subect가 발행한 알림에 대한 현재 상태를 취한다. Subject의 업데이트에 대해 전후 정보를 처리한다.

public class Observer : IObserver
{
    private int observerState;
    private string name;
    private ConcresteSubject subject;
	
    // 생성자를 통해서 자신이 관찰할 주체를 정하고 그 주체와 연결 설정
    public Observer(string name, ConcresteSubject subject)
    {
        this.name = name;
        this.subject= subject;
    }
    
    // 주체로부터 상태 변경 알림 받았을 때 호출
    public void Update(int newState)
    {
        observerState = newState;
        Console.WriteLine($"Observer{name} {observerState}")
    }
}

 


구체적인 주체와 주체 차이점

구체적인 주체는 이 개념적인 역할을 구현하면서 실제 상태변화를 감지하고 관찰자들에게 알림을 주는 기능을 수행한다.

주체는 개념적인 역할을 수행한다. 이는 주체와 관찰자 사이의 상호작용을 조정하고 관리하는데 책임을  가지고 있다.


구체적인 관찰자와 관찰자 차이점

구체적인 관찰자는 실제로 주체와 상호작용하면서 동작을 수행하는 객체이다. 예를 들어 게임 캐릭터는 주체의 변화를 받아들이면서 게임 내에서 동작을 수행한다.

관찰자는 상태 변화를 감지하면서 관찰자들에게 전달하는 중개자 역할을 한다.


2. 코드 실행

01 주체와 관찰자들 객체 만들기

private void Start()
{   
    ConcreteSubject subject = new ConcreteSubject();
    
    ConcreteObserver observer1 = new ConcreteObserver("observer1", subject);
    ConcreteObserver observer2 = new ConcreteObserver("observer2", subject);
    ConcreteObserver observer3 = new ConcreteObserver("observer3", subject);
}

02  주체 목록에 관찰자들 객체 넣기

subject.AttachObs(observer1);
subject.AttachObs(observer2);
subject.AttachObs(observer3);

03 정보 갱신한 다음 알림, 결과 출력

subject.SetState(5);


04 Observer1 삭제하고 정보 갱신한 다음 알림, 결과 출력

subject.DetachObs(observer1);
subject.SetState(10);


장점

Subject의 상태 변경을 주기적으로 조회하지 않고 자동으로 감지할 수 있다.

발행자의 코드를 변경하지 않고도 새 구족다 클래스를 도입할 수 있어 개방폐쇄 원칙을 준수한다.

 

단점

구독자는 알림 순서를 제어할 수 없고, 무작위 순서로 알림을 받는다.

옵저버 패턴을 자주 구성하면 구조와 동작을 알아보기 힘들어져 코드 복잡도가 증가한다.

3. 결과

주체 객체의 상태 변화를 여러 관찰자 객체들에게 알리고 싶을때 사용한다. 관찰자들은 주체의 상태 변화에 따라 적절한 동작을 수행한다. 예를 들어 게임에서 플레이어의 체력이 감소함에 따라 바로 체력 바를 업데이트할 수 있다. 그렇기 때문에 동일한 데이터를 참조하고 있을 때 효율적으로 동기화하고 업데이트 할 수 있다.

반응형

댓글