观察者形式完成非直接耦合

近来在看设想形式,一本《Head First 设想形式》,一本《javascript设想形式》,两本交替着看。Head First浅显易懂,代码用java完成,明白了一个设想形式的理念今后,先想想用js怎样完成,然后再看js设想形式相干章节,觉得比之前看的时刻明白深入了些。

本日早上看到颜海镜同砚在早读课上分享的耦合关联一文,末了一种模块间非直接耦合的完成体式格局第一个让我想到的就是视察者形式。恰好上午没事,就写了个demo完成了一下。

非直接耦合:两个模块之间没有直接关联,它们之间的联络完全是经由过程主模块的掌握和调用来完成的。耦合度最弱,模块独立性最强。子模块无需晓得对方的存在,子模块之间的联络,悉数变成子模块和主模块之间的联络。

《观察者形式完成非直接耦合》

现在要完成如许的功用:

  1. 一切模块只和主模块通信,能够把本身的变化示知主模块,也能够从主模块接收信息并处置惩罚;

  2. 主模块担任监听一切其下的模块的变化,一旦以为该变化须要关照到指定一个或多个其他模块,就向这些模块发送音讯。

大致完成思绪是:

子模块包括一个主模块的援用,在实例化要领中将其对应的主模块实例作为参数赋值给本身的主模块援用。

constructor(hub) {
    this._hub = hub;
}
    

子模块一致完成监听要领observeFromHub,供主模块触发实行本身的视察要领,详细由子类完成。

observeFromHub() {
    throw new Error('no implementation.');
}

子模块一致完成将本身的变化示知主模块的要领update(value)

update(value){
    this._hub.observeFromModule(value);
}

主模块包括一个子模块列表

constructor(){
    this.modules = [];
}

子模块一致完成add/remove要领,将本身增加到主模块的子模块列表modules中。

add(hub) {
    var alreadyExists = hub.modules.some((el)=>el === this);
    if (!alreadyExists) hub.modules.push(this);
    return this;
}

remove(hub) {
    hub.modules = hub.modules.filter((el)=>el !== this);
    return this;
}

主模块完成触发子模块列表中一切子模块的监听要领。

deliver(data){
    this.modules.forEach((module) => module.observeFromHub(data));
    return this;
}

主模块完成监听要领observeFromModule,供子模块触发实行本身的视察要领,由此来感知子模块的变化,进而实行deliver要领关照其下一切子模块。

observeFromModule(data) {
    return this.deliver(data);
}

有些要领子模块是公用的,所以能够将这些大众要领提取出来作为子模块的笼统超类

CommonModule.js

module.exports = class CommonModule {
    constructor(hub) {
        this._hub = hub;
    }
    
    update(value){
        this._hub.observeFromModule(value);
    }

    observeFromHub() {
        throw new Error('no implementation.');
    }

    add(hub) {
        var alreadyExists = hub.modules.some((el)=>el === this);
        if (!alreadyExists) hub.modules.push(this);
        return this;
    }

    remove(hub) {
        hub.modules = hub.modules.filter((el)=>el !== this);
        return this;
    }
}

observeFromHub要领有子模块本身完成。这里建立两个子模块Module1和Module2。当修正Module1时,主模块关照Module2实行observerFromHub(value)要领:

Module1.js

var CommonModule = require('./CommonModule');
module.exports = class Module1 extends CommonModule{
    constructor(hub) {
        super(hub);
        this.inputValue = '';
    }

    update(value) {
        this.inputValue = value;
        console.log('module1 setInput start... :' + this.inputValue);
        super.update(value);
    }
}

Module2.js

var CommonModule = require('./CommonModule');
module.exports = class Module2 extends CommonModule{
    constructor(hub) {
        super(hub);
        this.outputValue = '';
    }

    observeFromHub(value) {
        this.outputValue = value;
        console.log('module2 received msg : ' + this.outputValue);
    }
}

主模块代码:

Hub.js

module.exports = class Hub {
    constructor(){
        this.modules = [];
    }

    observeFromModule(data) {
        return this.deliver(data);
    }
    
    deliver(data){
        this.modules.forEach((module) => module.observeFromHub(data));
        return this;
    }
}

客户端代码:

main.js

var Hub = require('./Hub');
var Module1 = require('./Module1');
var Module2 = require('./Module2');

var hub = new Hub;
var inputModule = new Module1(hub);
var outputModule = new Module2(hub);

outputModule.add(hub);

inputModule.update('this is m1 speaking...');

实行main.js效果:

module1 setInput start... :this is m1 speaking...
module2 received msg : this is m1 speaking...

这个例子中主模块既是视察者,视察ModuleA的变化,又是被视察者,被ModuleB视察着,A一有变化就会将信息发送给B。

还能想到的一些风趣变化:

  1. 主模块能够有多个,各自统领的局限差别,但有些子模块能够会在多个局限中公用。

  2. 主模块中增加掌握器,数据需不须要下发,下发到那几个子模块,由主模块掌握。

    原文作者:梦梦她爹
    原文地址: https://segmentfault.com/a/1190000006829168
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞