资讯专栏INFORMATION COLUMN

观察者模式实现非直接耦合

binaryTree / 1075人阅读

摘要:子模块统一实现监听方法,供主模块触发执行自己的观察方法,具体由子类实现。子模块统一实现将自己的变化告知主模块的方法主模块包含一个子模块列表子模块统一实现方法,将自己添加到主模块的子模块列表中。

最近在看设计模式,一本《Head First 设计模式》,一本《javascript设计模式》,两本交替着看。Head First浅显易懂,代码用java实现,理解了一个设计模式的理念以后,先想想用js如何实现,然后再看js设计模式相关章节,感觉比以前看的时候理解深入了些。

今天早上看到颜海镜同学在早读课上分享的耦合关系一文,最后一种模块间非直接耦合的实现方式第一个让我想到的就是观察者模式。正好上午没事,就写了个demo实现了一下。

非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。耦合度最弱,模块独立性最强。子模块无需知道对方的存在,子模块之间的联系,全部变成子模块和主模块之间的联系。

现在要实现这样的功能:

所有模块只和主模块通讯,可以把自己的变化告知主模块,也可以从主模块接受信息并处理;

主模块负责监听所有其下的模块的变化,一旦认为该变化需要通知到指定一个或多个其他模块,就向这些模块发送消息。

大体实现思路是:

子模块包含一个主模块的引用,在实例化方法中将其对应的主模块实例作为参数赋值给自己的主模块引用。

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。

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

主模块可以有多个,各自管辖的范围不同,但有些子模块可能会在多个范围中公用。

主模块中添加控制器,数据需不需要下发,下发到那几个子模块,由主模块控制。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80340.html

相关文章

  • 一文理清21种设计模式:用实例分析和对比

    摘要:设计模式无论是对于最底层的的编码实现还是较高层的架构设计都有着重要的指导作用。所谓光说不练假把式,今天我就把项目中常见的应用场景涉及到的主要设计模式及其相关设计模式总结一下,用实例分析和对比的方式在一片文章中就把最常见的种设计模式梳理清楚。 设计模式无论是对于最底层的的编码实现还是较高层的架构设计都有着重要的指导作用。所谓光说不练假把式,今天我就把项目中常见的应用场景涉及到的主要设计模...

    PrototypeZ 评论0 收藏0
  • “大话”设计模式

    摘要:抽象工厂模式是为了处理对象具有等级结构以及对象族的问题。单例设计模式单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类。 导语:设计模式是无数码农前人在实际的生产项目中经过不断的踩坑、爬坑、修坑的经历总结出来的经验教训,经过抽象之后表达成的概念。能够帮助后来的设计者避免重复同样的错误或者弯路。我也抽空整理了一下设计模式,用自己的话总结了一下,自认...

    coordinate35 评论0 收藏0
  • 通俗易懂的设计模式

    摘要:面向对象设计模式通常以类别或对象来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类别或对象。里氏代换原则里氏代换原则是面向对象设计的基本原则之一。 通俗易懂的设计模式 零、使用 1、安装 2、测试 一、什么是设计模式 二、设计模式的类型 三、设计模式的六大原则 四、UML类图 1、看懂UML类图 2、解释 五、资料 前言:花了一些时间再次熟悉了一遍...

    wuyangnju 评论0 收藏0
  • 架构师必收藏的干货!!!

    摘要:一微服务概念微服务体系结构由轻量级松散耦合的服务集合组成。每个服务都有自己的计划测试发布部署扩展集成和独立维护。团队不必因为过去的技术决定而受到惩罚。用在这里是指将相关的服务通过聚合器聚合在一起,这个聚合器就是门面。 微服务架构现在是谈到企业应用架构时必聊的话题,微服务之所以火热也是因为相对之前的应用开发方式有很多优点,如更灵活、更能适应现在需求快速变更的大环境。 一、微服务概念 微服...

    shiweifu 评论0 收藏0
  • python设计模式

    摘要:在本节实验中,我们学习了四种设计模式策略模式,观察者模式,命令模式以及模板方法模式。这四种设计模式都是行为型模式。这就是适配器模式。下面让我们看看适配器模式在实验楼中使用吧。准确来说,装饰者模式能动态的给对象添加行为。 1、策略模式 策略模式将各种操作(算法)进行封装,并使它们之间可以互换。互换的意思是说可以动态改变对象的操作方式(算法)。 -- coding: utf-8 -- im...

    array_huang 评论0 收藏0

发表评论

0条评论

binaryTree

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<