관찰자 패턴이란?
공급자의 상태가 조건을 만족하거나 공급자에 변경이 발생 한 경우에, 델리게이트 또는 이벤트를 호출하여, 등록되어 있는 관찰자에게 전달해준다.
관찰자는 델리게이트 또는 이벤트 호출을 통해서 동작을 수행할 수 있다.
관찰자 패턴은 공급자와 관찰자 사이의 1 대 n의 관계를 가진다. 관찰자들은 필요한 공급자들에 등록을 해주며, 공급자들은 여러 관찰자에게 공급을 해준다.
Event를 이용한 구현
using System;
public class Subject//싱글톤 GameManager에서 사용 가능
{
public Action<int> scoreUpdate = null;
private int score = 0;
public int Score
{
get
{
return score;
}
set
{
score = value;
scoreUpdate?.Invoke(score);
}
}
}
using UnityEngine;
public class Observer : MonoBehaviour
{
private void Start()
{
GameManager.scoreUpdate += ShowScore;
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
GameManager.Score++;
}
}
public void ShowScore(int score)
{
Debug.Log(score);
}
}//실행 결과 : 점수가 바뀔 때마다, 점수가 log로 출력됨.
Interface를 이용한 구현
public interface ISubject
{
public void AddObserver(IObserver observer);
public void RemoveObserver(IObserver observer);
public void Notify();
}
public interface IObserver
{
public void UpdateValue(Object obj);
}
using System.Collections.Generic;
public class Subject : ISubject//싱글톤 GameManager에서 사용 가능
{
public List<IObserver> observerList = new();
private int count = 0;
public int Count
{
get
{
return count;
}
set
{
count = value;
Notify();
}
}
public void AddObserver(IObserver observer)
{
observerList.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
if(observerList.Contains(observer))
{
observerList.Remove(observer);
}
}
public void Notify()
{
foreach(IObserver observer in observerList)
{
observer.UpdateValue(this);
}
}
}
using UnityEngine;
public class Observer : MonoBehaviour, IObserver
{
private void Start()
{
GameManager.subject.AddObserver(this);
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
GameManager.subject.Count++;
}
}
public void UpdateValue(object obj)
{
if(obj is Subject)
{
Subject subject = obj as Subject;
Debug.Log(subject.Count);
}
}
}//실행 결과 : 점수가 바뀔 때마다, 점수가 log로 출력됨.
Event와 Interface를 이용한 구현의 차이
Event
- 공급자가 Event를 통하여서 관찰자에 상태를 전달한다.
- Event 등록과 해제로 간편하게 사용 가능하다.
Interface
- Intreface를 통해서 공급자와 관찰자에 대하여 정확한 구분과 관계가 잘 드러나 있다.
예시 상황
게임의 점수를 실시간으로 UI에 표시된다.
점수가 신기록을 갱신하였을 때, 파티클 효과를 재생한다.
위의 예시 상황을 관찰자 패턴을 사용하지 않고 구현한다면, 점수를 실시간으로 표시해 주며, 신기록을 갱신하였는지 확인을 Update 또는 반복기에서 진행하게 될 것이다. 위와 같은 구현은 의문이 생길 수 있다.
"점수가 바뀔 때만 점수를 업데이트하고, 신기록을 갱신하였는지 확인해도 되는 것 아닌가?"
위의 예시 상황에서 관찰자 패턴을 적용한다면, 점수가 변경되었을 때마다 관찰자들에게 전달하여서 불필요한 반복 작업을 줄일 수 있다. 또한 공급자 내에서 신기록 갱신 여부를 확인해서 , 파티클 효과를 재생해주는 관찰자에게 전달해 줄 수 있다.
'유니티 > 개념 정리' 카테고리의 다른 글
| EventSystem (0) | 2024.10.07 |
|---|---|
| ScriptableObject (0) | 2024.09.30 |
| 상속 (0) | 2024.09.23 |
| StopWatch와 Time.deltaTime (0) | 2024.09.12 |
| This (0) | 2024.09.09 |