Javascript 设计模式系统讲解与应用

442 阅读2分钟

一、JavaScript设计模式简介

设计模式我们其实听过不少,但是当别人问具体是什么或者有哪些设计模式的时候,我们有可能会不知道或者回答不全。其实我们在开发的过程中可能很少会用到设计模式,因为很多东西别人都帮我们封装好了,我们直接拿过来用即可。

前端的开发经过一遍封装过后变得无比容易,我们在运用的过程中得心应手,只有在源码阅读的过程中才会看到。

二、Javascript 设计模式系统讲解与应用

我们来看某课网上的这套《Javascript 设计模式系统讲解与应用》,几乎各种设计模式都有讲到,非常到位。以下是各个章节的简单介绍。

1 课程介绍
学习设计模式的必要性,课程包含的知识点,课程安排,学习前提

2 面向对象
讲解javascript中的面向对象的概念,包括 ES6 class 语法、UML 类图、以及面向对象三要素。

3 设计原则
设计原则是理解设计模式的基础,是从设计到模式的过度。本章介绍何为设计,5大原则,另外,还会讲解两个关于面向对象与设计原则的真实面试题。

4 工厂模式
工厂模式是我们最常用的实例化对象模式,本章介绍工厂模式的基本概念,以快餐店汉堡作为生活实例加深理解,讲解并绘制了UML类图,最后列举了JS中的常见使用场景,如 jquery中的$,React.createElement,vue 异步组件等。

5 单例模式
单例模式的核心结构中只包含一个被称为单例的特殊类。概念、UML类图仍是必须,本章使用的场景是 jquery中只有一个$,redux 和 vuex 的 store,一个系统中只有一套登录逻辑。

6 适配器模式
将一个类的接口适配成用户所期待的,这就是适配器。替换老项目中jquery的$.ajax,vue中计算机属性computed的使用,都可以看作是适配器模式。

7 装饰器模式
装饰器模式属于结构型模式,它是作为现有的类的一个包装,允许向一个现有的对象添加新的功能,同时又不改变其结构。本章同样介绍概念、UML。同时使用了丰富/实用的场景示例,包括ES7装饰器、core-decorators模块等。

8 代理模式
为其他对象提供一种代理以控制对这个对象的访问。网络代理,明星/经纪人的场景恰如其分。

9 外观模式
本章讲解外观模式,讲解其概念、示例。

10 观察者模式
观察者模式是前端最常用、最重要的设计模式,如果让你只掌握一种设计模式,那肯定就是观察者模式!!!星巴克点咖啡就是比较帖近的生活场景, jquery和NodeJs中的自定义事件更是经典的使用。

11 迭代器模式
用于顺序访问集合对象的元素,是的,就是循环。自己封装,通用的循环方法就是迭代器模式的经典实现。

12 状态模式
对于复杂的状态管理,如果只用 if…else来判断,扩展性是非常差的。状态模式提出了一种处理复杂状态变化且扩展性好的设计思路。有限状态机、自己实现Promise等场景的讲解,经典而深入。

13 其他设计模式
本章统一讲解一些 JS 中使用不是很频繁的设计模式。虽然不常用,但是也要理解其概念和用意。

14 综合应用
设计模式好学,不易用。最难的是不知道在什么场景下应该使用什么模式。本章以一个简单的购物车综合示例来演示几个常用的设计模式如何落地使用,包括项目的分析、设计、编码和设计模式解析。

15 设计模式总结
需要本套视频教程请私信或联系小编。

三、单例模式实例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

  <script>
    /*就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,
    这就确保了一个类只有一个实例对象在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问来访问该对象。*/
    
    // 单例模式 核心代码
    function Person() {
      this.name = 'Jack'
    }

    // 全局
    var instance = null

    function singleton() {
      if (instance === null) {
        instance = new Person()
      }
      return instance
    }

    /*
      singleton 第一次调用的时候
        + if 条件判断, 判断 instance === null
        + 现在自己作用域里面没有 instance, 去到 父级作用域访问
        + 也就是拿到了 全局作用域的 instance
        + 现在 全局的 instance 就是一个 null, if 条件为 true
        + 给 instance 赋值给 一个 Person 的实例(实例 001)
        + 现在全局的 instance 的值就是 实例001
        + return instance 就是 return 实例001
        + p1 得到的就是 实例001
    */
    var p1 = singleton()

    /*
      singleton 第二次调用的时候
        + if 条件判断, 判断 instance === null
        + 现在自己作用域里面没有 instance, 去到 父级作用域访问
        + 也就是拿到了 全局的 instance
        + 现在 全局的 instance 就是一个 实例001
        + if 条件不满足, 代码不执行
        + return instance 就是 return 实例001
        + p2 得到的依旧是 实例001
    */
    var p2 = singleton()

    // p1 和 p2 得到的都是第一次执行的时候的 实例
    // 他们两个其实是一个地址
    console.log(p1 === p2) // true
  </script>
</body>
</html>

更多前端实战教程,请看点:大前端+移动端学习视频教程

四、观察者模式实例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

  <script>
     /*
        观察者模式的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,
    就应该考虑使用观察者模式。
    */
   
    // 需要两个构造函数(被观察者和观察者)
    // 1. 被观察者(学生, 小明)
    class Student {
      constructor () {
        //constructor就相当于 es5 的构造函数体是一个 构造器
        // 一个学生本身的状态, 应该是好好学习
        this.state = '好好学习'
        // 准备一个数组,放监视学生的人
        // 将来一旦状态从 好好学习 变成 玩手机的时候, 就让这个 [] 里面的所有老师触发技能
        this.observers = []
      }

      // 方法
      // 1. 可以改变状态的方法
      setState (value) {
        // 可以把自己的状态改变
        this.state = value
        // 状态一旦改变, 就要通知监视他的人
        this.notify()
      }

      // 2. 获取自己的状态
      getState () {
        return this.state
      }

      // 3. 添加观察着
      // 向 this.observers 里面追加一个看着这个同学的人
      attach (observer) {
        this.observers.push(observer)
      }

      // 4. 通知 this.observers 数组里面的每一个人, 状态改变了
      notify () {
        this.observers.forEach(item => item.qingjiazhang( this.state ))
      }

    }

    // 2. 观察着(老师, 班主任, 教学主任, 年级主任, ...)
    class Observer {
      constructor (name) {
        // 用它来标明一下老师的类别
        this.name = name
      }

      // 方法, 就是这些老师能触发的技能
      qingjiazhang (state) {
        console.log(`我是 ${ this.name }, 因为你 ${ state } 了, 我要请你家长来!`)
      }
    }

    var xiaoming = new Student() // 被观察者

    var banzhuren = new Observer('班主任') // 观察者
    var jiaowuzhuren = new Observer('教务主任') // 观察者
    var nianjizhuren = new Observer('年级主任') // 观察者
    // 让班主任看着小明
    xiaoming.attach(banzhuren)
    // 让教务主任看着小明
    xiaoming.attach(jiaowuzhuren)
    // 让年级主任看着小明
    xiaoming.attach(nianjizhuren)

    // 当小明状态改变的时候
    //   xiaoming.setState() 就能改变 小明 现在的状态
    //   就会触发 xiaoming.notify()
    //   就会把 xiaoming.observers 这个数组里面的每一个对象的 请家长技能调用
    xiaoming.setState('玩手机') 
    console.log(xiaoming)

  </script>
</body>
</html>