Observer (オブザーバー)
観察者、監視者、etc...
Observerパターンとは、あるオブジェクトの状態の変化を、他のオブジェクトに通知するためのパターンです。状態を通知する側をSubject(被検者)、通知を受ける側をObserver(監視者)とみなして、SubjectにObserverを登録し、登録されたObserverすべてに対して変更を通知します。
以下に例を示します。
- Observerのインターフェースを定義する。 通知を受け取るためのメソッドを定義します。
public interface IObserver
{
void Notify(string from, string to, string subject);
}
- Subjectのインターフェースを定義する。 Observerの登録、Observerの登録解除、Observerへの通知を行うメソッドを定義します。
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObserver();
}
- ISubjectインターフェースを実装したMailManagerクラスを定義する。内部にIObjectクラスのコレクションを保持し、RegisterObserverでAdd、RemoveObserverでRemoveを行う。そして、NotifyObserverではIObjectのコレクションすべてに対して、Notifyメソッドの呼び出しを行う。
public class MailManager : ISubject
{
private List<IObserver> observers;
private string from;
private string to;
private string subject;
public MailManager()
{
observers = new List<IObserver>();
}
public void RegisterObserver(IObserver observer)
{
observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer);
}
public void NotifyObserver()
{
foreach ( IObserver observer in observers )
{
observer.Notify(from, to, subject);
}
}
public void SetData(string from, string to, string subject)
{
this.from = from;
this.to = to;
this.subject = subject;
NotifyObserver();
}
}
- IObserverインターフェースを実装したFaxクラス、Printerクラスを定義する。 それぞれ、通知を受けたときの動作を記述します。
public class Fax : IObserver
{
public void Notify(string from, string to, string subject)
{
Console.WriteLine("Faxを送信します。");
Console.WriteLine("From:{0}, To:{1}, Subject:{2}", from, to, subject);
}
}
public class Printer : IObserver
{
public void Notify(string from, string to, string subject)
{
Console.WriteLine("印刷します。");
Console.WriteLine("From={0}, To={1}, Subject={2}", from, to, subject);
}
}
以上のコードを実行してみます。
実行用コード
class ObserverTest
{
static void Main(string[] args)
{
MailManager mm = new MailManager();
Fax fax = new Fax();
mm.RegisterObserver(fax);
Console.WriteLine("1回目");
mm.SetData("わんくま同盟", "まさる", "勉強会の連絡");
Printer printer = new Printer();
mm.RegisterObserver(printer);
Console.WriteLine("2回目");
mm.SetData("わんくま同盟", "まさる", "補足");
mm.RemoveObserver(fax);
Console.WriteLine("3回目");
mm.SetData("わんくま同盟", "まさる", "訂正");
}
}
実行結果
1回目
Faxを送信します。
From:わんくま同盟, To:まさる, Subject:勉強会の連絡
2回目
Faxを送信します。
From:わんくま同盟, To:まさる, Subject:補足
印刷します。
From=わんくま同盟, To=まさる, Subject=補足
3回目
印刷します。
From=わんくま同盟, To=まさる, Subject=訂正
上記のように、登録されたObserverにSubjectの変更が通知され、処理されているのが確認できます。また、Observerの登録解除が正しく行われているのも確認できます。
ところで、Observerパターンの動作ですが、あるオブジェクトから通知を受ける「モノ」の登録、削除を行い、登録された「モノ」すべてに対して通知を行うというところが、なんとなく「イベント」に似てますね。
次回はその辺をちょっと掘り下げてみようと思います。