JS设计模式

设计模式是为了更好的代码重用性,可读性,可靠性,可维护性。
1、工厂模式:简单工厂模式 工厂模式 抽象工厂模式
新建立一个工厂 去根据具体需要去几种建立或者分发到不同的工厂去实例化对象
简单工厂:比如我要生产一个手机 一个工厂根据传入参数的不同去分别实例化华为和苹果的手机
工厂模式:比如我要生产一个手机 有一个总工厂 根据传入的品牌 去通知不同的工厂生产手机 然后返回
抽象工厂:生产手机更加具体 比如芯片和电池都是不同的工厂

2、单例模式: 保证一个类只能实例化一个对象 (比如登录和购物车)在实例化的时候判断是否有 没有才创建新实例返回
所以实例化出来的对象都是相等的

3、适配器模式: 类似于生活中的转换器 让不兼容的东西兼容
相当于 我想要的不是你 但是把你转换成我想要的 这转换过程就是适配器模式
比如vue的计算属性

//HTML代码

Original message: "{{ message }}"

Computed reversed message: "{{ reversedMessage }}"

//javascirpt var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } }) //显示结果 Original message: "Hello" Computed reversed message: "olleH"

4、装饰器模式: 简单说就是在不改变自身的情况下 对原有的类进行功能增加和扩展
为对象添加新功能
不改变其原有的结构和功能

class Circle {
    draw() {
        console.log("画一个圆形");
    }
}

class Decorator {
    constructor(circle){
        this.circle = circle;
    }
    draw() {
        this.circle.draw();
        this.setRedBorder(this.circle);
    }
    setRedBorder(circle) {
        console.log("设置红色边框")
    }
}
// 测试代码
let circle = new Circle();
circle.draw()

let dec = new Decorator(circle);
dec.setRedBorder();

利用AOP给函数动态添加功能,即Function的after或者before
应用场景:ES7装饰器、Vuex中1.0版本混入Vue时,重写init方法、Vue中数组变异方法实现等

5、代理模式:为其他对象提供一种代理,便以控制对这个对象的访问,不能直接访问目标对象
https://www.cnblogs.com/loveyt/p/11410593.html

这里的图片预加载相使用代理模式 相当于 myImage就只负责创建节点 设置src
而代理对象才是去再设置图片之前去加载一层预加载图片 相当于我们加载某个图片的时候我们直接去访问代理对象
于文档中代码 我们可能封装一下 传入2个参数 一个预加载的本地图片地址 和 服务器上的正式图片地址 即可复用
应用场景:ES6 Proxy、Vuex中对于getters访问、图片预加载等

6、外观模式
为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易,不符合单一职责原则和开放封闭原则
我感觉跟工厂模式有点像呢。。。

class A {
    eat () {}
}
class  B {
    eat () {}
}
class C {
    eat () {
        const a = new A();
        const b = new B();
        a.eat();
        b.eat();
    }
}
// 跨浏览器事件侦听器
function addEvent(el, type, fn) {
    if (window.addEventListener) {
        el.addEventListener(type, fn, false);
    } else if (window.attachEvent) {
        el.attachEvent('on' + type, fn);
    } else {
        el['on' + type] = fn;
    }
}

应用场景:JS事件不同浏览器兼容处理、同一方法可以传入不同参数兼容处理等

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

 class Subject {
  constructor () {
    this.state = 0;
    this.observers = [];
  }
  getState () {
    return this.state;
  }
  setState (state) {
    this.state = state;
    this.notify();
  }
  notify () {
    this.observers.forEach(observer => {
      observer.update();
    })
  }
  attach (observer) {
    this.observers.push(observer);
  }
}


class Observer {
  constructor (name, subject) {
    this.name = name;
    this.subject = subject;
    this.subject.attach(this);
  }
  update () {
    console.log(`${this.name} update, state: ${this.subject.getState()}`);
  }
}

let sub = new Subject();
let observer1 = new Observer('o1', sub);
let observer2 = new Observer('o2', sub);

sub.setState(1);

观察者模式与发布/订阅模式区别: 本质上的区别是调度的地方不同
虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者),但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
---观察者模式:目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法。
比如有个“天气中心”的具体目标A,专门监听天气变化,而有个显示天气的界面的观察者B,B就把自己注册到A里,当A触发天气变化,就调度B的更新方法,并带上自己的上下文。
---发布/订阅模式:订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者注册到调度中心的处理代码。
比如有个界面是实时显示天气,它就订阅天气事件(注册到调度中心,包括处理程序),当天气变化时(定时获取数据),就作为发布者发布天气信息到调度中心,调度中心就调度订阅者的天气处理程序。
应用场景:JS事件、JS Promise、JQuery.$CallBack、Vue watch、NodeJS自定义事件,文件流等

8、迭代器模式
提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示
可分为:内部迭代器和外部迭代器
内部迭代器: 内部已经定义好迭代规则,外部只需要调用一次即可
应用场景: JQuery.each方法
外部迭代器:必须显示的请求迭代下一个元素
简单来说就是需要显示的调用一些方法才能去迭代 不是直接调用方法来一步到位
应用场景:JS Iterator、JS Generator

9、状态模式
状态模式的使用场景也特别明确,有如下两点:
①一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
②一个操作中含有大量的分支语句,而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示。
简而言之,当遇到很多同级if-else或者switch的时候,可以使用状态模式来进行简化
应用场景:灯泡状态、红绿灯切换等
理解起来好难
https://www.jb51.net/article/92120.htm

上面所有的参考自:
https://juejin.im/post/5c984610e51d45656702a785

你可能感兴趣的:(JS设计模式)