반응형
옵저버 패턴이란?
- 한 객체가 주체 역할을 하고 다른 객체가 관찰자 역할을 맡는 객체 간의 일대다 관계를 설정하는 것이 핵심!!
- 주체 역할을 맡은 객체는 내부에서 변경되었을 때 관찰자에게 알리는 책임을 진다.
사용하는 이유?
- 상태를 자주 변경하고 변경 사항을 대응해야 하는 종속성이 많은 컴포넌트가 있다면 해당 패턴을 사용하는 것을 추천!
예제
1. 연결/해제/알림
public abstract class Subject : MonoBehaviour
{
...
protected void Attach(Observer observer)
{
_observers.Add(observer);
}
protected void Detach(Observer observer)
{
_observers.Remove(observer);
}
protected void NotifyObservers()
{
foreach (Observer observer in _observers)
{
observer.Notify(this);
}
}
}
* Attach - 알림받을 관찰자 목록에 객체를 추가
* Detach - 관찰자 목록에서 관찰자를 삭제
* NotifyObsercers - 주체의 관찰자 목록에 추가된 모든 객체에 알림을 보냄
위와 같이 코드를 구성하여 관찰자 역할을 맡은 객체는 Notify()라는 메서드를 구현하여 상태가 변경되었을 때 알림을 진행한다.
2. 옵저버 추상 클래스 (알림)
public abstract class Observer : MonoBehaviour
{
public abstract void Notify(Subject subject);
}
옵저버가 되고자 하는 클래스는 Observer 클래스를 상속받아 추상 메서드 구현을 진행
3. 연결과 해제 방법
public class BikeController : Subject, IBikeElement, IDamageable, IDestructible
{
...
private GameObject _hud;
private HUDController _hudController;
void OnEnable()
{
if (_hudController) Attach(_hudController);
}
void OnDisable()
{
if (_hudController) Detach(_hudController);
}
}
옵저버 패턴은 활성화/비활성화에 따라 연결과 해제를 해주는 것이 중요하다!
4. 관찰자에게 상태 업데이트 (알림)
public class BikeController : Subject
{
...
private bool _isEngineOn;
private HUDController _hudController;
void Awake()
{
_hudController =
gameObject.AddComponent<HUDController>();
...
}
private void Start()
{
StartEngine();
}
private void StartEngine()
{
_isEngineOn = true;
NotifyObservers();
}
public void ToggleTurbo()
{
if (_isEngineOn)
IsTurboOn = !IsTurboOn;
NotifyObservers();
}
public void TakeDamage(float amount)
{
NotifyObservers();
if (health < 0)
Destroy(gameObject);
}
}
Bike의 상태를 관찰자에게 알린다. 관찰자가 알림을 받게 되면 독립적으로 행동 방식을 정할 수 있다
5. 관찰자 (주체가 신호를 보내면 행동하는 부분)
public class HUDController : Observer
{
...
public override void Notify(Subject subject) {
if (!_bikeController)
_bikeController =
subject.GetComponent<BikeController>();
if (_bikeController) {
_isTurboOn =
_bikeController.IsTurboOn;
_currentHealth =
_bikeController.CurrentHealth;
}
}
}
속성에 접근하여 인터페이스에 표시할 속성들을 선택할 수 있다! 변경된 사항을 듣고 어떻게 반응할지 선택하는 것은
관찰자의 재량이다!
장단점
- 장점 :
- 역동성 : 주체에 필요한 만큼의 객체를 관찰자로 추가할 수 있고, 런타임에 동적으로 제거할 수도 있다.
- 일대다 : 옵저버 패턴의 주요 이점인 일대다 관계로 객체 간 이벤트 처리 시스템의 구현 문제를 편리하게 해결할 수 있다.
- 단점 :
- 무질서 : 옵저버 패턴은 관찰자가 알림받는 순서를 보장하지 않는다. 즉 둘 이상의 옵저버 객체가 종속성을 공유하고 특정 순서에 맞춰 동작해야 하는 것이라면 해당 패턴은 적당하지 않다!
- 누수 : 주체는 관찰자에 대한 강한 참조를 가져 메모리 누수를 일으킬 수 있다 . 그렇기 때문에 제대로 분리 및 삭제를 해주어야 한다!
반응형
'C# 프로그래밍 > 기초 문법' 카테고리의 다른 글
[c#] 디자인 패턴 - 상태 패턴 (0) | 2024.07.28 |
---|---|
[c#] 디자인 패턴 - MVC 패턴 (1) | 2024.07.23 |
[c#] 인터페이스란 (0) | 2024.07.14 |
[코딩테스트] c# 달리기 경주 (0) | 2023.07.20 |
c# 프로그래밍 - 구조체(truct) (0) | 2022.12.06 |