JS设计模式

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

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

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

//HTML代码
<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

//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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,192评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,186评论 1 303
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,844评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,471评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,876评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,891评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,068评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,791评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,539评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,772评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,250评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,577评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,244评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,146评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,949评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,995评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,812评论 2 276

推荐阅读更多精彩内容

  • 设计模式 单例 单例模式的核心思想是让指定的类只存在唯一一个实例。这意味着当你第二次使用相同的类去创建对象的时候,...
    代码上的蚂蚁阅读 482评论 0 0
  • 工厂模式 单体模式 模块模式 代理模式 职责链模式 命令模式 模板方法模式 策略模式 发布-订阅模式 中介者模式 ...
    HelloJames阅读 997评论 0 6
  • 2018任务繁重,今年打算把重点放在js的深入上,往大前端方向发展.年初有空看完了《JavaScript高级程序设...
    丶丶夏天阅读 722评论 1 2
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,018评论 1 10
  • 发布(Publish)/订阅(Subscribe)模式是一种和观察者(Observer)模式很相似的设计模式,以至...
    卓三阳阅读 3,907评论 1 6