• 《JavaScript设计模式与开发实践》整理


    最近在研读一本书《JavaScript设计模式与开发实践》,进阶用的。

    一、高阶函数

    高阶函数是指至少满足下列条件之一的函数。

    1. 函数可以作为参数被传递

    2. 函数可以作为返回值输出

    1)高阶函数实现AOP

    AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。

    把这些功能抽离出来之后,再通过“动态织入”的方式掺入业务逻辑模块中。

    这样做的好处首先是可以保持业务逻辑模块的纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块。

    在 JavaScript 中实现 AOP,都是指把一个函数“动态织入”到另外一个函数之中,查看demo

    Function.prototype.before = function( beforefn ){
        var __self = this;    // 保存原函数的引用
        return function(){    // 返回包含了原函数和新函数的"代理"函数
            beforefn.apply( this, arguments );     // 执行新函数,修正 this
            return __self.apply( this, arguments );    // 执行原函数
        }
    };
    Function.prototype.after = function( afterfn ){
        var __self = this;
        return function(){
            var ret = __self.apply( this, arguments );
            afterfn.apply( this, arguments ); 
            return ret;
        }
    };
    
    var func = function(){
        console.log( 2 );
    };
    func = func.before(function(){
        console.log( 1 );
    }).after(function(){
        console.log( 3 ); 
    });
    func();//1 2 3

    2)currying

    函数柯里化(function currying)又称部分求值

    一个 currying 的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。

    待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。简单点说就是返回一个函数。demo查看

    var cost = (function() {
      var args = [];
    
      return function() {
        if (arguments.length === 0) {
          var money = 0;
          for (var i = 0, l = args.length; i < l; i++) {
            money += args[i];
          }
          return money;
        } else {
          [].push.apply(args, arguments);
        }
      }
    })();
    
    cost(100); // 未真正求值
    cost(200); // 未真正求值
    cost(300); // 未真正求值
    console.log(cost()); // 求值并输出:600

    二、设计模式

    1)单例模式

    定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    单例模式的核心是确保只有一个实例,并提供全局访问。

    惰性单例。

    demo代码

    2)策略模式

    定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

    这句话如果说得更详细一点,就是:定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。在客户对 Context 发起请求的时候,Context 总是把请求委托给这些策略对象中间的某一个进行计算。

    计算奖金、缓动动画、表单校验。

    demo代码

    3)代理模式

    代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

    代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。

    保护代理和虚拟代理,虚拟代理实现图片预加,缓存代理,用高阶函数动态创建代理。

    demo代码

    4)迭代器模式

    迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

    内部迭代器和外部迭代器,

    demo代码

    5)发布—订阅模式

    发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

    DOM事件, 自定义事件,通用实现。

    demo代码

    6)命令模式

    命令模式中的命令(command)指的是一个执行某些特定事情的指令。

    命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。

    此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

    菜单程序,撤消命令,命令队列。

    demo代码

    7)组合模式

    组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构。

    除了用来表示树形结构之外,组合模式的另一个好处是通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性。

    宏命令,扫描文件夹。

    demo代码

    8)模板方法模式

    模板方法模式是一种只需使用继承就可以实现的非常简单的模式。

    模板方法模式由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。

    在模板方法模式中,子类实现中的相同部分被上移到父类中,而将不同的部分留待子类来实现。这也很好地体现了泛化的思想。

    Coffee or Tea,钩子方法,好莱坞原则。

    demo代码

    9)享元模式

    享元(flyweight)模式是一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级。

    享元模式的核心是运用共享技术来有效支持大量细粒度的对象。

    通用结构,通用对象池。

    demo代码

    10)职责链模式

    职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    职责链的实现,用AOP实现职责链

    demo代码

    11)中介者模式

    中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。

    泡泡堂。

    demo代码

    12)装饰者模式

    装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。

    飞机大战,装饰函数,用AOP 装饰函数 。

    demo代码

    13)状态模式

    允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

    第一部分的意思是将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态改变时,会带来不同的行为变化。

    第二部分是从客户的角度来看,我们使用的对象,在不同的状态下具有截然不同的行为,这个对象看起来是从不同的类中实例化而来的,实际上这是使用了委托的效果。

    通用结构,文件上传,JavaScript 版本的状态机。

    demo代码

    14)适配器模式

    适配器模式主要用来解决两个已有接口之间不匹配的问题,它不考虑这些接口是怎样实现的,也不考虑它们将来可能会如何演化。

    适配器模式不需要改变已有的接口,就能够使它们协同作用。

  • 相关阅读:
    Java:面向对象的编程语言
    Java基本数据类型
    NotePad++安装及配置
    MarkDown的黄金搭档Typora编辑器
    rabbitmq常用命令【转载】
    rabbitmqweb管理端口http://localhost:15672/ 无法访问可能出现的问题
    又一个关于TP5的坑 模板页注释了的 {aaa} 依然是会被访问的
    关于layui的分页
    使用TP5容易遇到的坑
    TP5访问不了控制器
  • 原文地址:https://www.cnblogs.com/strick/p/5895969.html
Copyright © 2020-2023  润新知