• 同步模块模式


    同步模块模式

    同步模块模式SMD是请求发出后,无论模块是否存在,立即执行后续的逻辑,实现模块开发中对模块的立即引用,模块化是将复杂的系统分解为高内聚、低耦合模块,同步模块模式不属于一般定义的23种设计模式的范畴,而通常将其看作广义上的架构型设计模式。

    描述

    同步模块模式通常用来解决如下场景的问题,随着页面功能的增加,系统的业务逻辑越来越复杂,多人开发的功能经常耦合在一起,有时项目经理提出的需求,分配给多人实现的时候,常常因为某一处功能耦合了多人的代码,从而出现排队修改的现象。
    通过使用模块化来分解复杂的系统可以很好的去解决这个问题,要想实现模块化开发,首先就需要有一个模块管理器,其管理着模块的创建与调度,对于模块的调用分为两类,第一类就是同步的模块调度,实现相对比较简单,不需要考虑模块间的异步加载,第二类的异步模块调度就比较繁琐,其可以实现对模块的加载调度。

    实现

    // 定义模块管理器单体对象
    var F = F || {};
    // 创建模块的方法define
    // str 模块路由; fn 模块方法
    F.define = function(str, fn){   // 定义模块方法,本应该在闭包中定义,这里先忽略
        let parts = str.split("."); // 解析模块路由str
        // 如果在闭包中,为了屏蔽对模块的直接访问,建议将模块添加给闭包内部私有变量
        // old,当前模块的祖父模块;parent,当前模块父模块
        let old = this;
        let parent = this;
        // i模块层级,len模块层级长度
        let i = 0;
        // 如果第一个模块是模块管理器单体对象,则移除
        if(parts[0] === "F") parts = parts.slice(1);
        // 屏蔽对define与module模块方法的重写
        if(parts[0] === "define" || parts[0] === "module") return void 0;
        // 遍历路由器并定义每层模块
        for(let len = parts.length; i < len; i++){
            // 如果父模块中不存在当前模块,声明当前模块
            if(parent[parts[i]] === void 0) parent[parts[i]] = {};
            // 缓存下一级的祖父模块
            old = parent;
            // 缓存下一级的父模块
            parent = parent[parts[i]];
        }
        // 如果给定模块方法fn则定义改模块方法
        if(fn){
            // 此时i等于parts.length,故减1
            old[parts[--i]] = fn();
        }
        return this;    // 返回模块管理器单体对象
    }
    
    // 用上面的方法来创建模块
    // 创建模块k,并对该模块提供t方法
    F.define("k", function(){
        return {
            t: function(){
                console.log("it is function t")
            }
        }
        //也可以以构造函数的方法返回
        /* let xx = function(){};
        xx.t = function(){
            console.log("this is xx.t")
        }
        xx.tt = function(){
            console.log("this is xx.tt")
        }
        return xx; */
    });
    
    // 使用t方法,但正式的模块开发不允许直接调用
    // 一是因为模块通常为闭包中的私有变量,不会保存在F上,获取不到,这里简化没有使用闭包
    // 二是因为这样调用不符合模块开发规范
    F.k.t();
    // 用构造函数返回时的调用方法
    /* F.k.t();
    F.k.tt(); */
    
    // 也可先声明模块再定义方法
    F.define("a.b")
    F.a.b = function(){
        console.log("this is function from a.b")
    }
    F.a.b();
    
    // 由于不能直接调用,就需要调用模块的方法
    // 调用模块的方法module
    // 参数分两部分,依赖模块与回调函数(最后一个参数)
    // 原理是遍历获取所有依赖模块,并保存在依赖模块列表中,然后将这些依赖模块作为参数传入执行函数中执行
    F.module = function(...args){
        let fn = args.pop();    // 获取回调执行函数
            // 获取依赖模块,若args[0]是数组,则它为依赖模块,否则为args
        let parts = args[0] && args[0] instanceof Array ? args[0] : args;
        let modules = [];   // 依赖模块列表
        let modIDs = "";    // 模块路由
        let i = 0;  // 依赖模块索引
        let ilen = parts.length;    // 依赖模块长度
        // 遍历依赖模块
        parts.forEach(v => {
            if(typeof v === "string"){   // 如果是模块路由
                let parent = this;  // 设置当前模块父对象(F)
                // 解析模块路由,并屏蔽掉模块父对象
                modIDs = v.replace(/^F./, "").split(".");
                // 遍历模块路由层级
                for(let j = 0; j < modIDs.length; j++){
                    parent = parent[modIDs[j]] || false;    // 重置父模块
                }
                modules.push(parent);   // 将模块添加到模块依赖列表
            }else{  // 如果是模块对象
                modules.push(v); // 直接加入模块依赖列表
            }
        })
        fn.apply(null, modules);    // 执行回调函数
    }
    
    // 依赖dom和k模块的方法,数组形式
    F.module(["dom", "k"], function(){
        console.log(1);
    })
    // 依赖dom2模块和k.a方法,字符串形式
    F.module("dom2", "k.a", function(){
        console.log(2);
    })
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://www.jianshu.com/p/2359390737aa
    https://www.dazhuanlan.com/2020/03/09/5e65fa05c9bb7/
    https://blog.csdn.net/WuLex/article/details/107350493
    
  • 相关阅读:
    代码块语法
    js数据验证
    EF之POCO应用系列2——示例入门
    EF之POCO应用系列1——POCO
    圣诞节快来了!祝福代码
    我们为什么需要校友录 如何下载校友资料
    我们为什么需要校友录 打造富有个性的个人空间
    我们为什么需要校友录 如何使用多条件搜索功能寻找校友
    我们为什么需要校友录 如何利用“校友活动”功能组织一次精彩的校友聚会
    我们为什么需要校友录 如何打造多采的相册专辑
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/14250657.html
Copyright © 2020-2023  润新知