IOS里的定义了NSNotification来实现观察者模式(NSNotificationCenter是观察者模式和中介者模式的融合,而且还是个单例,它负责集中管理通知者和观察者)。
而C#里定义了delegate和event这种广播委托/事件来实现观察者模式(参考C#语法小知识(四)委托delegate和C#语法小知识(九)事件),这种方式非常易用且好用。但是我们不妨把这些放在一边,自己来探究观察者模式的实现。
首先我们定义一个观察者的接口:
public interface IObserver{
void ReceiveEvent (string eventName, object obj);
}
public class Notification
{
protected Dictionary> _observers = new Dictionary>();
public virtual void AddObserver(IObserver obs, string eventName)
{
if (!_observers.ContainsKey (eventName)) {
_observers [eventName] = new List ();
}
_observers [eventName].Add (obs);
}
public virtual void RemoveObserver(IObserver obs, string eventName)
{
if (!_observers.ContainsKey (eventName)) {
return;
}
_observers [eventName].Remove (obs);
}
public virtual void RemoveAllEvents(IObserver obs)
{
foreach (var kv in _observers) {
kv.Value.Remove (obs);
}
}
public virtual void PostNotification(string eventName, object obj)
{
if (!_observers.ContainsKey (eventName)) {
return;
}
List obsList = _observers [eventName];
foreach (IObserver obs in obsList) {
obs.ReceiveEvent (eventName, obj);
}
}
}
我们不妨定义一个邮箱的类作为实例:
public class MailBox : Notification
{
public void ReceiveMail(string mail)
{
PostNotification ("MAIL_RECEIVED", mail);
}
}
收到邮件的时候,发送事件出去。public class MailObserver : IObserver
{
public void ReceiveEvent (string eventName, object obj)
{
Console.WriteLine ("[" + eventName + "]" + obj);
}
}
使用:
MailBox mb = new MailBox ();
MailObserver mo1 = new MailObserver ();
MailObserver mo2 = new MailObserver ();
mb.AddObserver (mo1, "MAIL_RECEIVED");
mb.AddObserver (mo2, "MAIL_RECEIVED");
mb.ReceiveMail ("Hello");
如果你觉得让邮箱继承Notification这种方式不好,那么我们也可以实现一个IOS的NSNotificationCenter风格的通知中心:
public sealed class NotificationCenter
{
private static NotificationCenter _center = new NotificationCenter();
public static NotificationCenter defaultCenter
{
get {
return _center;
}
}
Dictionary
在MailBox的ReceiveMail方法里添加:
NotificationCenter.defaultCenter.PostNotification (this, "MAIL_RECEIVED", mail);
NotificationCenter.defaultCenter.AddObserver (mb, mo1, "MAIL_RECEIVED");
NotificationCenter.defaultCenter.AddObserver (mb, mo2, "MAIL_RECEIVED");
mb.ReceiveMail ("World");
public class NewMailBox
{
public delegate void MailReceived(object msg);
public MailReceived mailReceivedDelegate;
public void ReceiveMail(string mail)
{
mailReceivedDelegate.Invoke (mail);
}
}
public class NewMailObserver
{
public void ReceiveEvent (object obj)
{
Console.WriteLine ("[Mail received]" + obj);
}
}
NewMailBox nmb = new NewMailBox ();
NewMailObserver nmo = new NewMailObserver ();
nmb.mailReceivedDelegate = nmo.ReceiveEvent;
nmb.mailReceivedDelegate += (object mail) => {
Console.WriteLine (mail);
};
nmb.ReceiveMail ("New");
1、实现了目标和观察者的抽象耦合
2、支持广播通信
缺点:因为一个观察者并不知道其他观察者的存在,它可能对改变目标的最终代价一无所知,在目标上一个看似无害的操作可能会引起一系列观察者以及依赖于观察者的对象的更新。并且如果依赖准则定义或维护不当,容易引起错误的更新,并且难以排错。
而且维护观察者的时候需要额外注意,当观察者需要析构的时候,要提前移除监听,否则会出错。