观察者模式(Observer):在对象间定义一种
一对多
的依赖关系,以便当某对象的状态改变时,与它存在依赖关系的所有对象都能收到通知并自动进行更新。
- MVC模式的底层可以说就是利用了观察者模式
基础设计
我们可以使用如下的方式设计一个简单的观察者模式,在被观察者中需要存储一个观察者组,提供一个发送消息的方法对观察组进行消息推送。
在观察者中提供一个消息响应的方法,响应消息。
/// <summary>
/// 事件
/// </summary>
public enum Event
{
捡到金币,
通关
}
/// <summary>
/// 观察者接口
/// </summary>
public interface IObserver
{
/// <summary>
/// 接收通知
/// </summary>
/// <param name="subject"></param>
/// <param name="eventMsg"></param>
void OnNotify(Subject subject, Event eventMsg);
}
/// <summary>
/// 被观察者接口
/// </summary>
public interface ISubject
{
List<IObserver> Observers();
void AddObserver(IObserver observer);
void RemoveObserver(IObserver observer);
}
/// <summary>
/// 观察者
/// </summary>
public class Observer : IObserver
{
public void OnNotify(Subject subject, Event eventMsg)
{
switch (eventMsg)
{
case Event.捡到金币:
subject.Score += 10;
break;
case Event.通关:
subject.Score += 100;
break;
}
}
}
/// <summary>
/// 被观察者
/// </summary>
public class Subject : ISubject
{
public int Score;
private readonly List<IObserver> _observers;
/// <summary>
/// 发送消息
/// </summary>
/// <param name="eventMsg"></param>
public void Notify(Event eventMsg)
{
_observers.ForEach(x=>x.OnNotify(this,eventMsg));
}
public Subject()
{
_observers = new List<IObserver>();
}
public List<IObserver> Observers()
{
return _observers;
}
public void AddObserver(IObserver observer)
{
_observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
_observers.Remove(observer);
}
}
使用委托和事件
在Csharp中内置了委托和事件来处理这种一对多的响应方式。
using System;
namespace ObserverPattern
{
/// <summary>
/// 观察者模式
/// </summary>
internal static class Program
{
public static void Main(string[] args)
{
var c = new Cat() {Name = "小白"};
var m = new Mouse(c) {Name = "小鼠"};
c.OnCatCom();
}
}
class Cat
{
public string Name { get; set; }
public event Action catCom;
public virtual void OnCatCom()
{
Console.WriteLine("{0}来了",Name);
catCom?.Invoke();
}
}
class Mouse
{
public string Name { get; set; }
public Mouse(Cat cat)
{
//将事件绑定到方法
cat.catCom += this.MouseRun;
}
private void MouseRun()
{
Console.WriteLine("{0}快跑!!",Name);
}
}
}
思考
其实观察者模式就是对象的一种间接同步调用
,使用这种方法是为了解除耦合,达到统一分配管理的作用。
从上文提到的可以知道,这种模式是同步的,也就是说当存在一组观察者时,那么可能会导致阻塞
,但在实际中可能没这么严重,但在使用中我们还需注意。
如果你在每次响应后给出一个状态,表示通知的响应情况,那么这就接近
责任链模式
了。
销毁对象?
在书中提到一个问题很有趣,在观察者模式中销毁对象该怎么办呢?
在销毁对象前,需要解除监听,确保对象被正确销毁。
现状
观察者模式出现于1994年(比我还大😄),因此基本都是基于类来实现的,但现在更流行
函数式编程
,可能不太符合现在的编程美学。例如C#的event就是现代化的观察者模式。