从观察者模式说起

观察者模式

观察者模式的定义

Observer(观察者)是一种设计模式, 其中, 一个对象(称为 subject) 维持一系列依赖于它的观察者对象, 将有关状态的任何变更自动通知给观察者.
当一个目标(subject)需要告诉观察者发生了什么有趣的事情, 它会向观察者广播一个通知. 当我们不再希望某个特定的观察者获得其注册目标(subject)发出的改变通知时, 该目标可以将它从观察者列表中删除.

“一个或多个观察者对目标的状态感兴趣, 它们通过将自己依附在目标对象上以便注册所感兴趣的内容. 目标状态发生改变并且观察者可能对这些改变感兴趣, 就会发送一个通知消息, 调用每个观察者的更新方法. 当观察者不再对目标状态感兴趣时, 它们可以简单地将自己从中分离.” ———《设计模式: 可复用面向对象软件基础》

观察者模式的理解

从观察者模式的定义中可以对观察者模式有个大体的了解. 观察者模式中有两类, 一类被称为目标(Subject), 一类被称为观察者(Observer). Subject的工作是维护一系列的Observer, 可以对它们进行添加、删除和通知的操作. Observer的工作则是为Subject状态发生变化需要获得通知的对象提供更新接口.

戏说观察者模式

先不管观察者模式是什么, 我们可以试着想想如何从观察者模式的定义去实现这些功能. 下面我们从一个小故事说起.
从前有个人. 凭着天资聪颖再加上闯荡江湖多年, 无论从事什么行业都能称为行业翘楚, 算是有名气的人物.

1
class Subject {}        // 我是有个人. Subject是江湖送我的绰号.

有一天, 有一个初创公司慕名前来拜访, 探讨如何在现在这个激烈的竞争环境下赢得一席之地.

1
class Observer {}       // 我是一家初创公司, Observer是我公司的名字.

两人见面直奔主题.
‘你可以派些人来, 我给他们做培训. ’, Subject如此说道. Observer点头同意.
‘可是我如何才能让他们服从并执行呢?’, Subject问到. ‘我们可以向你提供统一的对接方式’, Observer回答到.
‘行, 谁要有兴趣谁就过来吧’

1
2
3
4
5
6
7
8
/* update是我们的对接方式, fn是我们的职能.
只需要走update这个流程, 我们会各司其职.
下面这是个我们的模子, 每个走出去的人都大体这样.*/
class Observer {
constructor(fn) {
this.update = fn
}
}

为了后续的开展, 夜曉宸也做了准备. 为随后要来的人腾出了空间, 并想好了如何接待每个人.

1
2
3
4
5
6
7
8
class Subject {
constructor() {
this.observesList = []; // 这里是为参与者腾出的空间.
}
addObserver(observer) {
this.observerList.push(observer); // 招待每一个参与者, 就是引导参与者进入腾出的空间.
}
}

不日, Observer派人带着各自本职职务过来了.

1
2
3
const observer1 = new Observer(() => {document.write(`${order}: 我是财务, 我要开始算绩效发工资了<br/>`));
const observer2 = new Observer(() => {document.write(`${order}: 我是后勤客服, 有什么事情需要帮助的?<br/>`));
const observer3 = new Observer(() => {document.write(`${order}: 我是人事, 我要招人了<br/>`));

既然人来了, 那就接待.

1
2
3
4
const subject = new Subject();      // 事务繁忙, 派了一个影分身.
subject.addObserver(observer1); // 引导observer1进入房间.
subject.addObserver(observer2); // 引导observer2进入房间.
subject.addObserver(observer3); // // 引导observer3进入房间.

‘既然来到了这个房间, 就要明确一点, 那就是你们得听我指令, 到时我会使用你们公司统一的对接方式’

1
2
3
4
5
6
7
class Subject {
// 省略
notify(context) {
// 由公司提供的统一对接方式,向在场的每一个Observer传达并让其执行.
this.observerList.forEach(observer => observer.update(context));
}
}

‘如果你们不想呆下去了, 可以和我说, 我可以引导你们出去’

1
2
3
4
5
6
7
8
class Subject {
// 省略
removeObserver(observer) {
// 对于不再感兴趣的Observer,可以将其剔除,其不会再收到任何来自Subject的通知.
let pos = this.observerList.indexOf(observer);
this.observerList.splice(pos, 1);
}
}

‘现在, 要下达指令了!’

1
2
// 省略
subject.notify('描述下各自的职能');

‘好了, 这些就是我们培训的内容, 就是这么简单’
‘就这么简单?!?, 既然这样, 就送我出去吧, 我不想再呆下去了 ’, observer2说到.

1
2
// 省略
subject.removeObserver(observer2);

到此故事告一段落了, Observer模式在线Demo.

再看观察者模式

我们从几段对话中, 稀里糊涂的完成了本文开头观察者模式所定义的那样. 有负责管理一系列依赖的对象, 有提供更新接口的对象. 我们可以看到, 当subject1发出通知时, 每个observe都能去执行. observer们的行为依赖于subject1的. 为什么能够做到这一点, 那是因为observe们的行为作为自身的一部分寄存在了subject1, subject1就可以在需要的时候去自己腾出的小屋子里通知observer们执行.
如果subject1 带着这么一波参加过培训的observer们回去交差, 肯定会被笑话. subject1和observer们的这种协作方式, 被称做观察者模式. 这不过是一个模式, 何时存储何种东西, 何时又去执行存储的东西那才是关键. 如果放到上面的小故事里, 那就是何时需要何种人, 何时开始去做事, 这都需要审时度势. 只有这样公司才能在激烈的竞争环境中赢得一席之地. 只有这样, 观察者模式才能发挥它最大的作用.

------------- The End -------------
显示评论