옵서버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다.
(출처 : 위키백과)
간단하게 설명하면 어떤 주체의 옵저버 역할을 하고 싶은 객체가 옵저버로 등록을 하면 주체에서 어떤 데이터의 변경여부를 알려주거나 또는 조회할 수 있게 해주는 디자인 패턴이라고 할수 있을 것 같다.
상품이 있고 이 상품의 구매 가능여부를 상품에 대해 구독한 유저에게 알려준다고 가정하고 구현.
Subject를 하고 싶은 객체들은 Subject인터페이스만 구현하면 주체 역활을 할 수 있도록 인터페이스를 만든다.
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers();
}
그리고 객체 구현
public class Product : ISubject
{
private List<IObserver> _observers = new List<IObserver>();
private string _productName;
private string _productAvailability;
public Product(string productName)
{
_productName = productName;
_productAvailability = "Out of Stock";
}
public string ProductAvailability
{
get { return _productAvailability; }
set {
_productAvailability = value;
// _productAvailability의 내용이 변경될 때 옵저버들에게 변경 사실을 알림.
NotifyObservers();
}
}
public void RegisterObserver(IObserver observer)
{
_observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
_observers.Remove(observer);
}
public void NotifyObservers()
{
foreach (var observer in _observers)
{
observer.Update(_productAvailability);
}
}
}
RegisterObserver 와 RemoveObserver는 옵저버를 구독, 구독 취소하는 메서드.
_observers -> 옵저버 관리 리스트.
public string ProductAvailability
{
get { return _productAvailability; }
set {
_productAvailability = value;
// _productAvailability의 내용이 변경될 때 옵저버들에게 변경 사실을 알림.
NotifyObservers();
}
}
이 부분에서 ProductAvailability의 내용이 변경(set)될 때 NotifyObservers() 메서드를 호출하여 등록된 옵저버들에게 변경 내용을 알려준다.
Observer 인터페이스를 구현하면 옵저버가 될 수 있도록 인터페이스를 구현.
public interface IObserver
{
void Update(string availability);
}
availability 에 대한 옵저버 인터페이스.
public class User : IObserver
{
private string _userName;
public User(string userName, ISubject product)
{
_userName = userName;
// User 인스턴스를 product가 가지고 있는 옵저버 리스트에 등록.
product.RegisterObserver(this);
}
public void Update(string availability)
{
Console.WriteLine($"안녕하세요, {_userName}님! 제품의 가용성이 변경되었습니다: {availability}");
}
}
IObserver를 구현한 user 객체
생성자에서 ISubject 객체를 받아 이 자기 자신을 옵저버 리스트에 추가한다.
간단하게 콘솔에서 테스트를 해본다.
Product product = new Product("게임 콘솔");
User user1 = new User("Kane", product);
User user2 = new User("Big show", product);
Console.WriteLine("처음 제품 상태: " + product.ProductAvailability);
product.ProductAvailability = "In Stock";
product.ProductAvailability = "close to being sold out";
실행하면 product의 ProductAvailability 가 변경될 때 user의 update 메서드가 실행되는 것을 확인할 수 있다.
처음 제품 상태: Out of Stock
안녕하세요, Kane님! 제품의 가용성이 변경되었습니다: In Stock
안녕하세요, Big show님! 제품의 가용성이 변경되었습니다: In Stock
안녕하세요, Kane님! 제품의 가용성이 변경되었습니다: close to being sold out
안녕하세요, Big show님! 제품의 가용성이 변경되었습니다: close to being sold out
다음 포스트에서는 C#에 이벤트를 활용해서 구현하는 것을 공부해보려 한다.