[TOC]

1.1. javascript进阶

1.1.1. 设计模式

设计模式概论

项目 = 模块 + 沟通

  • 更好的组织模块

  • 设计模块之间的沟通

  • 提高代码质量,更加优雅

设计原则
  1. 开闭原则(对拓展开放,对源码关闭)

  2. 单一职责原则(一个模块的功能越单一越好)

  3. 依赖倒置原则(依赖抽象,而不是下层具体方法)

    上层接口不会被下层接口所影响,而是在中间加入抽象层,上层去依赖抽象层

  4. 接口隔离原则(细化接口功能,使单一)

  5. 迪米特法则(两个模块之间的联系越少越好)

  6. 里氏替换原则(任何父类使用的地方,子类可以替换)

设计模式的分类
  • 创建型

这些设计模式可以帮助我们优雅的创建对象

工厂模式 - 大量创建对象、单例模式 - 全局只能有我一个、建造者模式 - 精细化组合对象、原型模式 - JavaScript的灵魂

  • 结构型

帮助我们优雅的设计代码结构

外观模式 - 给你一个套餐、享元模式 - 共享来减少数量、适配器模式 - 用适配代替更改、桥接模式 - 独立出来,然后再对接过去(降低耦合度)、装饰者模式 - 更优雅的扩展需求

  • 行为型

模块之间行为的模式总结,帮助我们组织模块行为

观察者模式 - 我作为第三方转发、职责连模式 - 像生产线一样组织模块、状态模式 - 用状态代替判断、命令模式 - 用命令去解耦、策略模式 - 算法工厂、迭代器模式 - 告别for循环(forEach)

  • 技巧型

一些帮助我们优化代码的技巧

链模式 - 链式调用、惰性模式 - 机器学习、委托模式 - 让别人代替你收快递、等待着模式 - 等你们都回来在吃饭、数据访问模式 - 一个方便的数据管理器


封装与对象

封装的目的

  • 定义变量不会污染外部
  • 能够作为一个模块调用
  • 遵循开闭原则

好的封装满足:

  1. 变量外部不可见
  2. 调用接口来使用
  3. 流出扩展接口
工厂模式 - 大量创建对象

当某一个对象需要经常创建的时候(弹窗模块)

fuction Facroty(type){
  switch(type){
      case 'type1';
      return new Type1();
      case 'type2';
      return new Type2()
  }
}

示例:多彩的弹窗、Jquery、underscore

建造者模式 - 精细化组合一个全局对象

当需要创建单个、庞大的组合对象时(轮播图)

// 模块1
function model1(){}
// 模块2
function model2(){}
// 最终的类
function final(){
  this.mode1 = new model1()
  this.mode2 = new model2()
}

示例:编辑器插件,vue的初始化

单例模式 - 全局只能有我一个

为了避免重复新建,避免多个对象存在互相干扰

做法:通过定义一个方法,使用时只允许通过此方法拿到存在内部的同一个实例话对象

let Single = function(name){
  this.name = name
}
Single.getInstance = function(name){
  if(this.instance){
    return this.instance
  }
  return this.instance = new Single(name)
}

示例:全局数据储存对象,vue-router

提高可复用性

可复用性的目的

  • 遵循DRY原则
  • 减少代码量,节省开销

特点

  1. 对象可以重复使用,不用修改
  2. 重复代码少
  3. 模块功能单一
桥接模式

目的:桥接代替耦合

场景:减少模块之间的耦合

三种形状,每种形状有三种颜色

颜色部分抽出来作为公用方法,形状的类都依赖于这个方法。

通过独立方法之间的桥接来形成整体功能,这样每个方法都可以被高度复用

示例:菜单上每一项都有不同的选中效果(把颜色效果抽离出来,在桥接到菜单类上)、Express中创建get等方法

```



##### 享元模式

目的:减少对象/代码数量

场景:代码中创建了大量类似对象和类似代码块

有一百种不同文字的弹窗,每种弹窗行为相同,但是文字和样式不同

保留同样的行为,提取出每个弹窗的不同部分作为外部数组

> 提取出共有部分与私有部分,私有部分作为外部数据传入,从而减少对象/代码数量

示例:多个文件上传,Jquery的extend

```javascript
function extend(){
  if(arguments == 1){
    for(var item in arguments[0]){
      this[item] = arguments[0][item]
        }
  }else{
    for(var item in arguments[1]){
      arguments[0][item] = arguments[1][item]
        }
  }
}
function extend(){
  var target = arguments[0]
  var source
  if(arguments == 1){
    target = this
    source = arguments[0]
    }else{
    target = arguments[0]
    source = arguments[1]
  }
  for(var item in source){
    target[item] = source[item]
  }
}
模版方法模式

目的:定义系列操作的股价,简化后面类似操作的内容

场景:当项目中出现很多类似操作内容

先写一个基础类,特异性传入回调函数,具体实现放在回调函数。

当一个功能朝着多样化发展,不妨先定义一个基础类,把具体实现延迟到后面

示例:行为,大小,文字都会不同的一系列弹窗、封装一个算法计算器(不同地方增加不同操作)

JS组合和继承

组合和继承

提高代码质量

目的:

  • 高质量的代码,方便后续的一切操作
  • 方便他人阅读

好的代码:

  • 代码整洁
  • 结构规整,没有漫长的结构
  • 阅读好理解
策略模式/状态模式

将方法分为几个策略放在策略对象里,直接调用对象的相应策略就可以了

在策略对象里,加入状态变量,使用时通过盖面状态来调用相应的策略

示例:动态的内容(不同用户权限不同内容)

外观模式

多个简单的接口合并成一个高级的接口

迭代器模式

在不暴露对象内部的同时,可以按顺序的访问对象内部

示例:自己的forEach

function Iteratpr(data){
  this.data = data
}
Iterator.prototype.dealEach = function(fn){
  if (this.data instanceof Array){
    for(let i = 0; i<this.data.length;i++){
    fn(this.data[i],i)
    }
  }else{
    for(let item in this.data){
      fn(this.data[item],item)
    }
  }
}
备忘录模式

缓存对象记录对象内部的状态,有需要时回滚到之前的状态

设计轮播图

需求描述

  • 多种播放方式(渐显渐隐,左右滑动切换,上下滑动切换)

设计:

采用建造者模式来搭建模块框架

  1. 请求图片模块
  2. 检测图片加载模块(因为一般轮播图的图片比较大,而我们又需要在第一时间就展现出来,所以等待图片加载完成后再返回一个事件去渲染)
  3. 图片展示模块(此模块一般会重复四到六次,来展示不同的图片达到轮博的效果)
  4. 自动播放模块(放一个定时器,自动播放,切换图片)
  5. 图片的位置移动(在自动播放,或者手动切换的时候,调用此方法来实现图片的切换,在其中加入渐隐渐显的选择开关;一般采用translateX来实现移动,
  6. 触摸移动模块(在拖动图片的时候,会暂停自动播放模块,并根据用户的操作让图片产生暂时移动,并将上下的滑动按比例转化为水平滑动,检测滑动幅度超过阈值就调用位置移动模块,不超过则在触摸事件结束的时候弹回原位置,并开启自动播放模块
  7. 轮播图模块(综合以上几个模块,可以传入图片url,是否渐显渐隐等参数,并将参数传给相应模块将其进行柯里化,方便其他模块在调用的时候,不需要在传入初始值)

商品信息缓存器

需求描述:

(1)可根据商品id判断商品是否加载过,如果加载过,直接从缓存里拿;如没有,则请求;

(2)如果是热门商品,缓存于全局的对象里;如果是非热门商品,则缓存于localStorage中;全局对象和localStorage中的商品数量上限可以配置;

(3)可主动调用api来更新某个商品的信息。

© Jasonk0 all right reserved,powered by Gitbook该文件修订时间: 2022-07-21 08:53:32

results matching ""

    No results matching ""