观察者模式
背景
在软件系统中进场遇到这类需求:当一个对象的状态发生改变,某些与它相关的对象也要随之做出相应的变化。这是建立一种 对象域对象之前的依赖关系,一个对象发生变化时将自动通知其他对象,其他对象将做出反应。
我们将发生改变的对象称为观察目标,将被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互关系,之后可以根据需要增加和删除贯彻着,是的系统更易于扩展,这就是观察者模式的产生背景。
概念介绍
观察者模式(Observer Pattern):定义对象之间的一种 一对多依赖关系,使得每当一个对象状态发生改变时,其他依赖对象皆得到通知并被自动更新。观察者模式是一种对象行为型模式。
生活场景
所有浏览器事件(鼠标悬浮,按键等事件)都是观察者模式的例子。
模式特点
1.模式组成
在观察着模式中,通常包含以下角色:
a.目标(Subject)
b.观察目标(ConcresteSubject)
c.观察者(Observer)
d.具体观察者(ConcreteObserver)
2.UML类图

3.优点
- 观察者模式可以实现 表示层和数据逻辑层的分离,并降低观察目标和观察者之间的耦合度;
- 观察者模式支持简单广播通信,自动通知所有已经订阅过的对象;
- 观察者模式 符合开闭原则的要求;
- 观察目标和观察者之间的抽象耦合关系能够单独扩展以及中庸。
4.缺点
- 当一个观察目标有多个直接或间接的观察者时,通知所有观察者的过程将会话费很多时间。
- 当观察目标和观察者之间存在循环依赖时,观察目标会触发他们之间进行循环调用,可能导致系统崩溃。
- 观察者模式缺少相应机制,让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景
在以下情况下可以使用观察者模式:
- 在一个抽象模型中,一个对象的行为 依赖于另一个对象的状态。即当目标对象的状态发生改变是,会直接影响到观察者的行为;
- 一个对象需要通知其他对象发生反应,但不知道对象是谁。
- 需要在系统中创建一个触发链时,A对象的行为将影响B,B对象的行为将影响C对象......,可以使用观察者模式创建一种链式触发机制。
实战示例
1.定义观察目标接口 和观察者接口
//观察目标接口
interface Subject {
addObserver: (observer:Observer) => void;
deleteObserver:(observver:Observer) => void;
notifyObservers:() => void;
}
//观察者接口
interface Observer {
notify:() => void;
}
2.定义具体观察目标
//具体观察目标类
class ConcreteSubject implements Subject {
private observers: Observer[] = [];
//添加观察者
public addObserver(observer:Observer): void {
console.log(observer, "is pushed~~");
this.observers.push(observer);
}
//删除观察者
public deleteObserver(observer:Observer): void {
console.log(observer,"have deleted~~");
const idx:number = this.observers.indexOf(observer);
~idx && this.observsers.splice(idx,1);
}
//通知观察者
public notifyObservers(): void {
console.log('notify all the observers ',this.observers);
this.observers.forEach(observer => {
//调用 notify 方法时可以携带指定参数
observer.notify();
})
}
}
3.定义 具体观察类
//具体观察类
class ConcreteObserver implements Observer {
constructor(private name:string){}
notify():void {
//可以处理其他逻辑
console.log(`${this.name}has been notified.`);
}
}
4.测试代码
//测试代码~~~~
function userObserver(): void {
const subject: Subject = new ConcreteSubject();
const Leo = new ConcreteObserver('Leo');
const Robin = new ConcreteObserver('Robin');
const Pual = new ConcreteObserver('Pual');
const Lisa = new ConcreteObserver('Lisa');
subject.addObserver(Leo);
subject.addObserver(Robin);
subject.addObserver(Pual);
subject.addObserver(Lisa);
subject.notifyObservers();
}
本文使用 mdnice 排版