5分鐘通過一個例子理解觀察者模式和釋出訂閱模式的區別

雲峰yf發表於2018-08-04

前幾天在一個群裡閒聊的時候,有一個人問:觀察者模式和釋出訂閱模式到底有什麼區別?

雖然平時用的 vue、redux、node 或多或少會涉及到這兩個模式,但是卻沒有怎麼深入思考過它們兩者的區別。

於是我開始思考這個問題。

兩個模式之間的區別

關於這兩個模式之間的特點,hackernoon 有一篇文章分析的很好。

掘金上也有它的翻譯

總之,它倆最顯著的區別就是觀察者模式中觀察者和被觀察者是互相知道對方的存在的,而在釋出訂閱模式中是不知道的

由內推流程得到啟發

最近我司剛好開啟了校招,我也領了一個內推碼:XGBU3Z8。突然發現我司的社招內推就是一個觀察者模式,而校招內推是一個釋出訂閱模式。

位元組跳動校招連結

這從何說起呢?社招內推是需要求職者將簡歷給員工的,然後員工去內推系統新建內推。在這個過程中,內推者和求職者是需要知道彼此的存在的,當求職狀態發生變化時,內推者可以及時告知求職者。

而校招內推是員工釋出一個內推碼,然後哪個應屆生看見了內推碼就可以自行進行投遞。員工和應屆求職者之間理論上是不知道互相的存在的,他們只知道內推碼的存在。

社招內推

class JobFinder {
    constructor(id, job) {
        this.id = id;
        this.job = job;
        this.status = null;
    }

    subscribe(employee) {
        employee.jobFinderList.push(this);
    }

    unsubscribe(employee) {
        employee.jobFinderList = employee.jobFinderList.filter(person => person.id !== this.id)
    }

    update(status) {
        this.status = status;
        console.log(this.id + '知道自己求職狀態變更為:' + status);
    }
}

class Employee {
    constructor() {
        this.jobFinderList = [];
    }

    recommend(JobFinder) {
        JobFinder.subscribe(this);
    }

    notify(message) {
        this.jobFinderList.forEach(person => {
            const target = message.find(m => m.id === person.id)
            if (target) person.update(target.status);
        })
    }
}

var me = new Employee();

var zs = new JobFinder('張三', '前端工程師');
var ls = new JobFinder('李四', '後端工程師');

// 內推張三和李四
me.recommend(zs);
me.recommend(ls);

// 通知他們
setTimeout(() => {
    me.notify([
        { id: '張三', status: '簡歷評估中' }
    ]);
}, 1000)

setTimeout(() => {
    me.notify([
        { id: '張三', status: '面試中' }
    ]);
}, 500)

setTimeout(() => {
    me.notify([
        { id: '張三', status: 'offer' },
        { id: '李四', status: '簡歷評估中' }
    ]);
}, 2000)
複製程式碼

我們定義一個求職者 JobFinder 類,再定義一個員工 Employee 類。

這時有張三和李四這兩個求職者需要找工作,然後我內推了他們兩個,過了一段時間後我通知他們求職狀態發生變更。

在這個內推過程中,我必須要拿到他們的簡歷,獲取和他們有關的資訊,比如意向崗位等。

當然,這個例子很簡單,還可以加一些邏輯,比如面試掛了後就 unsubscribe 之類的。

校招內推

// 內推系統
const recommendSystem = document;

class Employee {
    constructor() {
        // 內推碼
        this.recommendCode = 'XGBU3Z8';
        this.recommendEvent = new CustomEvent(this.recommendCode)
    }

    notify(message) {
        this.recommendEvent = new CustomEvent(this.recommendCode, { detail: message });
        recommendSystem.dispatchEvent(this.recommendEvent)
    }
}

class JobFinder {
    constructor(id, job) {
        this.id = id;
        this.job = job;
    }

    submitResume(recommendCode) {
        recommendSystem.addEventListener(recommendCode, this.update.bind(this));
    }

    update(event) {
        const target = event.detail.find(m => m.id === this.id);
        if (target) console.log(this.id + '知道自己求職狀態變更為:' + target.status);
    }
}

var me = new Employee();

var zs = new JobFinder('張三', '前端工程師');
var ls = new JobFinder('李四', '後端工程師');

// 通過內推碼投簡歷
zs.submitResume('XGBU3Z8');
ls.submitResume('XGBU3Z8');

// 通知他們
setTimeout(() => {
    me.notify([
        { id: '張三', status: '簡歷評估中' }
    ]);
}, 1000)

setTimeout(() => {
    me.notify([
        { id: '張三', status: '面試中' }
    ]);
}, 500)

setTimeout(() => {
    me.notify([
        { id: '張三', status: 'offer' },
        { id: '李四', status: '簡歷評估中' }
    ]);
}, 2000)
複製程式碼

這段程式碼中同樣有一個求職者和員工類。但多了個內推系統作為我們的事件通道。

這時張三和李四找工作已經不需要我去操心了,我只需要在他們求職狀態變更時及時通知他們就可以了。

甚至我也不需要通知他們,而是由內推系統通知他們:

recommendSystem.dispatchEvent(new CustomEvent('XGBU3Z8', { detail: [
    { id: '張三', status: 'offer' },
    { id: '李四', status: '簡歷評估中' }
]}));
複製程式碼

結語

歡迎各位讀者耐心讀完這篇文章~如果身邊有應屆生在找工作,歡迎使用我的內推碼 XGBU3Z8 ~

當然,我手上還有一個白金內推碼,可以直通面試那種,如果讀者中有對自己能力足夠自信的應屆生,歡迎私聊我索要~

相關文章