JavaScript 工厂模式和订阅模式

简介: 设计模式的好处:代码规范// 例如表单验证,两个 input ,一个用户名,一个密码// 通常做法是function checkUser(){ //.....}function checkPassword(){ //.

设计模式的好处:

  1. 代码规范
// 例如表单验证,两个 input ,一个用户名,一个密码
// 通常做法是
function checkUser(){
    //.....
}
function checkPassword(){
    //.....
}
// 问题:
// 这是两个全局对象,而这两个方法属于一个表单的验证

// 所以这应该是一个表单对象,起码应该这么写
// 对象封装,但是注意全局对象
var checkObj = {
    checkUser: function() {
        //.....
    },
    checkPassword: function() {
        //.....
    }
}

// 问题:
// 对象过多
// 解决:闭包

(function(){
    //.....
})()

工厂模式

// ajax 为例
var xhr = new XMLHttpRequest(); // IE6不兼容XMLHttpRequest对象,需要使用ActiveXObject("Microsoft.XMLHTTP")
xhr.onreadystatechange = function(){

}
xhr.open();
xhr.send(null);
// 使用工厂模式
// 好处:低耦合,高内聚
var XMLHTTPFactory = function() {
    var XMLHTTP = null;
    if (window.XMLHttpRequest()){
        XMLHTTP = new XMLHttpRequest();
    } else {
        XMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return XMLHTTP;
}
// 使用
var xhr = XMLHTTPFactory();

订阅者模式

// 订阅者:买家
// 发布者:卖家
var showObj = {}; // 定义发布者
showObj.list = []; // 存储订阅者
// 增加订阅者,订阅消息
showObj.listen = function (fn) { // fn回调函数,输出你想输出的内容
    showObj.list.push(fn);
}
showObj.trigger = function () {
    for (var i = 0, fn; fn = this.list[i++];) {
        fn.apply(this, arguments);
    }
}

showObj.listen(function (color, size) {
    console.log("颜色是" + color);
    console.log("尺码是" + size);
})

showObj.listen(function (color, size) {
    console.log("再次输出颜色是" + color);
    console.log("再次输出尺码是" + size);
})

showObj.trigger("白色", 40);
showObj.trigger("黑色", 20);

// 你会发现输出了两遍,这是为什么呢?
// 原因就在于showObj.list.push(fn)
// 那么如何使不同的订阅者查看到属于自己的订阅呢

使用一个key区分

var showObj = {}; // 定义发布者
showObj.list = []; // 存储订阅者
// 增加订阅者,订阅消息
showObj.listen = function (key, fn) { // 在订阅的时候给一个标识
    if (!this.list[key]) {
        this.list[key] = [];
    }
    showObj.list[key].push(fn);
}
showObj.trigger = function () { // 发布的时候认识知道订阅的消息分别发布给谁
    // 取到消息名称
    var key = Array.prototype.shift.call(arguments);
    // 对应的回调函数
    var fns = this.list[key];
    if (!fns || fns.length === 0) {
        return;
    }
    for (var i = 0, fn; fn = fns[i++];) {
        fn.apply(this, arguments);
    }
}

showObj.listen("white", function (color, size) {
    console.log("小爱同学订阅的颜色是" + color);
    console.log("小爱同学订阅的尺码是" + size);
})

showObj.listen("black", function (color, size) {
    console.log("小冰同学订阅的颜色是" + color);
    console.log("小冰同学订阅的尺码是" + size);
})

showObj.trigger("white", "白色", 40);
showObj.trigger("black", "黑色", 20);
// 但是这样的写的话适用性太差,所以我们需要对其进行封装。

封装

var event = {
    list: [],
    listen: function (key, fn) { // 在订阅的时候给一个标识
        if (!this.list[key]) {
            this.list[key] = [];
        }
        this.list[key].push(fn);
    },
    trigger: function () { // 发布的时候认识知道订阅的消息分别发布给谁
        // 取到消息名称
        var key = Array.prototype.shift.call(arguments);
        // 对应的回调函数
        var fns = this.list[key];
        if (!fns || fns.length === 0) {
            return;
        }
        for (var i = 0, fn; fn = fns[i++];) {
            fn.apply(this, arguments);
        }
    },
    // 移除方法(取消订阅)
    remove: function (key, fn) {
        var fns = this.list[key];
        // 没有订阅过
        if (!fns) {
            return false;
        }
        // 回调函数为空
        if (!fn) {
            fn && (fns.length = 0);
        } else {
            for (var i = fns.length - 1; i >= 0; i++) {
                var _fn = fns[i];
                if (_fn === fn) {
                    fns.splice(i, 1);//删除订阅者的回调函数
                }
            }
        }
    }
};

var initEvent = function (obj) {
    for (var i in event) {
        obj[i] = event[i]
    }
}
var showObj = {};// 让任何一个普通对象都拥有发布订阅功能
initEvent(showObj);

showObj.listen("white", fn1 = function (color, size) {
    console.log("小爱同学订阅的颜色是" + color);
    console.log("小爱同学订阅的尺码是" + size);
})

showObj.listen("black", fn2 = function (color, size) {
    console.log("小冰同学订阅的颜色是" + color);
    console.log("小冰同学订阅的尺码是" + size);
})

showObj.trigger("white", "白色", 40);
showObj.trigger("black", "黑色", 20);
目录
相关文章
|
3月前
|
存储 安全 JavaScript
云计算浪潮中的网络安全之舵探索Node.js中的异步编程模式
【8月更文挑战第27天】在数字化时代的风帆下,云计算如同一片广阔的海洋,承载着企业与个人的数据梦想。然而,这片海洋并非总是风平浪静。随着网络攻击的波涛汹涌,如何确保航行的安全成为了每一个船员必须面对的挑战。本文将探索云计算环境下的网络安全策略,从云服务的本质出发,深入信息安全的核心,揭示如何在云海中找到安全的灯塔。
|
3天前
|
前端开发 JavaScript UED
探索JavaScript中的异步编程模式
【10月更文挑战第21天】在数字时代的浪潮中,JavaScript作为一门动态的、解释型的编程语言,以其卓越的灵活性和强大的功能在Web开发领域扮演着举足轻重的角色。本篇文章旨在深入探讨JavaScript中的异步编程模式,揭示其背后的原理和实践方法。通过分析回调函数、Promise对象以及async/await语法糖等关键技术点,我们将一同揭开JavaScript异步编程的神秘面纱,领略其带来的非阻塞I/O操作的魅力。让我们跟随代码的步伐,开启一场关于时间、性能与用户体验的奇妙之旅。
|
20天前
|
JavaScript 前端开发 API
探索Node.js中的异步编程模式
【10月更文挑战第4天】在JavaScript的世界中,异步编程是提升应用性能和用户体验的关键。本文将深入探讨Node.js中异步编程的几种模式,包括回调函数、Promises、async/await,并分享如何有效利用这些模式来构建高性能的后端服务。
|
23天前
|
JavaScript 前端开发 调度
探索Node.js中的异步编程模式
在Node.js的世界里,异步编程是核心。本文将带你深入了解异步编程的精髓,通过代码示例和实际案例分析,我们将一起掌握事件循环、回调函数、Promises以及async/await等关键概念。准备好迎接挑战,让你的Node.js应用飞起来!
|
30天前
|
JavaScript 前端开发 开发者
探索Node.js中的异步编程模式
【9月更文挑战第33天】在JavaScript的后端领域,Node.js凭借其非阻塞I/O和事件驱动的特性,成为高性能应用的首选平台。本文将深入浅出地探讨Node.js中异步编程的核心概念、Promise对象、Async/Await语法以及它们如何优化后端开发的效率和性能。
23 7
|
2月前
|
JavaScript 前端开发 开发者
探索Node.js中的异步编程模式
【9月更文挑战第15天】在Node.js的世界中,“一切皆异步”不仅是一句口号,更是其设计哲学的核心。本文将带你深入理解Node.js中异步编程的几种主要模式,包括经典的回调函数、强大的Promise对象、以及简洁的async/await结构。我们将通过实例代码来展示每种模式的使用方式和优缺点,帮助你更好地掌握Node.js异步编程的精髓。无论你是Node.js新手还是有一定经验的开发者,这篇文章都能给你带来新的启示和思考。让我们一起开启Node.js异步编程的探索之旅吧!
|
2月前
|
JavaScript 前端开发 中间件
深入浅出Node.js中间件模式
【9月更文挑战第13天】本文将带你领略Node.js中间件模式的魅力,从概念到实战,一步步揭示如何利用这一强大工具简化和增强你的Web应用。我们将通过实际代码示例,展示中间件如何在不修改原有代码的情况下,为请求处理流程添加功能层。无论你是前端还是后端开发者,这篇文章都将为你打开一扇通往更高效、更可维护代码的大门。
|
2月前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
3月前
|
设计模式 JavaScript 前端开发
Vue.js组件设计模式:构建可复用组件库
在Vue.js中,构建可复用组件库是提升代码质量和维护性的核心策略。采用单文件组件(SFC),定义props及默认值,利用自定义事件和插槽进行灵活通信,结合Vuex或Pinia的状态管理,以及高阶组件技术,可以增强组件的功能性和灵活性。通过合理的抽象封装、考虑组件的可配置性和扩展性,并辅以详尽的文档和充分的测试,能够打造出既高效又可靠的组件库。此外,采用懒加载、按需导入技术优化性能,制定设计系统和风格指南确保一致性,配合版本控制、CI/CD流程和代码审查机制,最终形成一个高品质、易维护且具有良好社区支持的组件库。
61 7
|
3月前
|
设计模式 JavaScript 前端开发
Vue.js 组件设计模式:在前端热潮中找到归属感,打造可复用组件库,开启高效开发之旅!
【8月更文挑战第22天】Vue.js 以其高效构建单页应用著称,更可通过精良的组件设计打造可复用组件库。组件应职责单一、边界清晰,如一个显示文本并触发事件的按钮组件,通过 props 传递标签文本,利用插槽增强灵活性,允许父组件注入动态内容。结合 CSS 预处理器管理和封装独立模块,配以详尽文档,有效提升开发效率及代码可维护性。合理设计模式下,组件库既灵活又强大,持续实践可优化项目工作流。
48 1