观察者模式是一种软件设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,它的所有依赖者(观察者)都将得到通知并自动更新。这种模式通过解耦合主题和观察者来提高对象的灵活性。
定义
观察者模式包括一个主题(Subject)和多个观察者(Observer)。当主题的状态改变时,它会通知观察者并调用它们的特定方法,使得观察者可以自动更新。
应用场景
观察者模式常见于以下场景:
-
当一个对象的变化需要通知其他对象,而且你无法确切知道有多少个对象需要通知时,可以使用观察者模式。
-
当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时使用观察者模式可以将这两者封装在独立的对象中,使它们各自独立地改变和复用。
优点
-
观察者模式降低了主题和观察者之间的耦合度,使得主题和观察者可以轻松地独立变化。
-
支持广播通信,观察者模式可以向多个对象同时发送通知。
缺点
-
如果观察者过多或通知机制过于复杂,容易导致性能问题。
-
如果观察者和主题之间存在循环依赖,可能会导致系统崩溃或出现死循环。
观察者模式是一种广泛应用的设计模式,在许多面向对象编程语言和框架中都有相应的实现,例如在事件处理、模型-视图-控制器 (MVC) 架构中都有观察者模式的影子。
Demo
1.Subject类
cs
internal abstract class SubjectBase
{
// 将所有观察者放入list集合
private readonly List<Observer> observers = new List<Observer>();
public event EventHandler<EventArgs> NotifyAllHandler;
public virtual void NotifyAllObserver()
{
NotifyAllHandler?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// 加入集合
/// </summary>
/// <param name="observer"></param>
public virtual void AttachObserver(Observer observer)
{
observers.Add(observer);
}
/// <summary>
/// 从观察者列表中去除
/// </summary>
/// <param name="observer"></param>
public virtual void RemoveObserver(Observer observer)
{
observers.Remove(observer);
}
}
internal class Subject: SubjectBase
{
}
2.Observer观察者抽象类
cs
/// <summary>
/// 观察者抽象类
/// </summary>
internal abstract class Observer
{
protected SubjectBase _subject;
/// <summary>
/// 更新消息
/// </summary>
public abstract void Update(object? sender, EventArgs eventArgs);
public virtual void SetSubject(SubjectBase subject)
{
if (subject == _subject) return;
if (this._subject != null)
{
this._subject.RemoveObserver(this);
this._subject.NotifyAllHandler -= Update;
}
this._subject = subject;
this._subject.AttachObserver(this);
this._subject.NotifyAllHandler += Update;
}
}
3.具体观察者,需要继承Observer基类
cs
internal class Observer_A : Observer
{
public override void Update(object? sender, EventArgs eventArgs)
{
Console.WriteLine($"Observer_A");
}
}
internal class Observer_B : Observer
{
public override void Update(object? sender, EventArgs eventArgs)
{
Console.WriteLine($"Observer_B");
}
}
调用
cs
// 发布类
SubjectBase subject = new Subject();
// 观察者
Observer observerA = new Observer_A();
observerA.SetSubject(subject);
Observer observerB = new Observer_B();
observerB.SetSubject(subject);
// 发布类间隔通知
await Task.Run(() =>
{
while (true)
{
subject.NotifyAllObserver();
Console.WriteLine("====================================================");
Thread.Sleep(3000);
}
});