옵저버 패턴(Observer Pattern)
설명 출처 : https://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4
졸업작품 하면서 디자인패턴을 공부했었는데 현재 블로그에 따로 정리한게 자주 쓰는 싱글톤 밖에 없었고 안쓰다보니 까먹은 것도 많고 복습도 할겸 조금씩 정리하려고 한다.
이 패턴의 핵심은 옵저버 또는 리스너(listener)라 불리는 하나 이상의 객체를 관찰 대상이 되는 객체에 등록시킨다. 그리고 각각의 옵저버들은 관찰 대상인 객체가 발생시키는 이벤트를 받아 처리한다.
UML 다이어그램으로는 아래처럼 표현된다. 관찰 대상인 객체는 “이벤트를 발생시키는 주체”라는 의미에서 Subject로 표시되어 있다.
이벤트가 발생하면 각 옵저버는 콜백(callback)을 받는다. notify
함수는 관찰 대상이 발행한 메시지 이외에, 옵서버 자신이 생성한 인자값을 전달할 수도 있다.
각각의 파생 옵서버는 notify
함수를 구현함으로써 이벤트가 발생했을 때 처리할 각자의 동작을 정의해야 한다.
주체에는 일반적으로 등록(register), 제거(unregister) 메서드가 있는데, 전자는 새로운 옵저버를 목록에 등록하고 후자는 목록에서 옵저버를 뺀다. 등록과 제거 메서드 이외에도, 임시로 작동을 멈추거나 재개하는 메서드를 이용해 이벤트가 계속해서 있을 때 홍수같이 발생하는 요청을 제어할 수도 있다.
옵서버 패턴이 많이 쓰인 시스템에서는 순환 실행을 막는 메카니즘이 필요하다. 이벤트 X가 발생하면 옵저버A가 옵저버B를 갱신한다고 가정해보자. 그런데 옵저버B가 이 처리를 위해 옵저버A를 갱신한다면, 이는 다시 A로 하여금 이벤트 X를 발생하게 한다. 이같은 상황을 막기 위해 이벤트 X가 한번 처리된 후에는 A가 이벤트 X를 다시 발생시키지 않는 방법이 요구된다.
C# Event에 옵저버패턴이 녹아져있다고 보면 된다.
http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&detail=1&pageno=0&wid=1283&rssMode=1&wtype=0
code>>
IObserver.cs
namespace Algorithm.DesignPattern.Observer
{
interface IObserver
{
void Notify(EventArgs args);
}
}
Subject.cs
namespace Algorithm.DesignPattern.Observer
{
class Subject
{
private List<IObserver> _observers;
public Subject()
{
_observers = new List<IObserver>();
}
public Subject Add(IObserver Item)
{
_observers.Add(Item);
return this;
}
public Subject Remove(IObserver Item)
{
_observers.Remove(Item);
return this;
}
public void Notify()
{
EventArgs args = new EventArgs();
foreach (var observer in _observers)
{
observer.Notify(args);
}
}
}
//Event 방식의 Observer
class SubjectEvent
{
public delegate void NotifyObserver(EventArgs args);
public event NotifyObserver NotifyEvent;
public SubjectEvent()
{
}
public void Notify()
{
EventArgs args = new EventArgs();
NotifyEvent(args);
}
}
}
Program.cs
namespace Algorithm
{
class ConcreateObserverA : DesignPattern.Observer.IObserver
{
public void Notify(EventArgs args)
{
Console.WriteLine("ConcreateObserverA");
}
}
class ConcreateObserverB : DesignPattern.Observer.IObserver
{
public void Notify(EventArgs args)
{
Console.WriteLine("ConcreateObserverB");
}
}
class Program
{
static void Main(string[] args)
{
DesignPattern.Observer.Subject subject = new DesignPattern.Observer.Subject();
ConcreateObserverA concreateObserverA = new ConcreateObserverA();
ConcreateObserverB concreateObserverB = new ConcreateObserverB();
subject.Add(concreateObserverA).Add(concreateObserverB);
subject.Notify();
DesignPattern.Observer.SubjectEvent subjectEvent = new DesignPattern.Observer.SubjectEvent();
subjectEvent.NotifyEvent += concreateObserverA.Notify;
subjectEvent.NotifyEvent += concreateObserverB.Notify;
subjectEvent.Notify();
}
}
}