观察者模式(Observer Design Pattern)
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。 消息队列 事件总线 就是观察者模式。
结构图:
角色:
- 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一组接口,可以增加和删除观察者对象。
- 具体主题(ConcreteSubject):将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知
- 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
- 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
适用场景:
- 需要通过事件触发场景。
优点:
- 可以很轻松的添加观察者/订阅者,符合开闭原则。
缺点:
- 如果观察者/订阅者过多通知将会很耗时。
- 无法保证通知的顺序。
代码(C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
public class MyBlog : Blog { public MyBlog(string title, string content) : base(title, content) { } }
public interface IObserver { void Update(Blog tenxun); }
public class ConcreteObserver : IObserver { public string Name { get; set; }
public ConcreteObserver(string name) { Name = name; }
public void Update(Blog blog) { Console.WriteLine($"订阅者 {Name} 观察到了{blog.title}{blog.content}"); } }
public abstract class Blog { private List<IObserver> observers = new List<IObserver>();
public string title { get; set; } public string content { get; set; }
public Blog(string title, string content) { this.title = title; this.content = content; }
public void AddObserver(IObserver ob) { observers.Add(ob); }
public void RemoveObserver(IObserver ob) { observers.Remove(ob); }
public void NotifyObservers() { foreach (var ob in observers) { ob.Update(this); } } }
Blog blog = new MyBlog("标题", "内容");
blog.AddObserver(new ConcreteObserver("1")); blog.AddObserver(new ConcreteObserver("2")); blog.AddObserver(new ConcreteObserver("3")); blog.AddObserver(new ConcreteObserver("4"));
blog.NotifyObservers();
|
最后
上面的代码算是观察者模式的模板代码,只能反映大体的设计思路。在真实的软件开发中,并不需要照搬上面的模板代码。观察者模式的实现方法各式各样,函数、类的命名等会根据业务场景的不同有很大的差别,万变不离其宗,设计思路都是差不多的
观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子。比如,邮件订阅、RSS Feeds,本质上都是观察者模式。不同的应用场景和需求下,这个模式也有截然不同的实现方式,有同步阻塞的实现方式,也有异步非阻塞的实现方式,有进程内的实现方式,也有跨进程的实现方式。