每次都忘记一些设计模式,这里记录一下常用的一些。
设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结,是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式原则
Single Responsibility Principle 单一职责原则 (S)
一个程序只做好一件事
如果功能过于复杂就拆分开,每个部分保持独立
OpenClosed Principle 开放/封闭原则 (O)
对扩展开放,对修改封闭
增加需求时,扩展新代码,而非修改已有代码
Liskov Substitution Principle 里氏替换原则 (L)
Interface Segregation Principle 接口隔离原则 (I)
保持接口的单一独立
类似单一职责原则,这里更关注接口
Dependency Inversion Principle 依赖倒转原则 (D)
面向接口编程,依赖于抽象而不依赖于具体
使用方只关注接口而不关注具体类的实现
SO 体现较多,举个栗子:(比如 Promise) 单一职责原则:每个 then 中的逻辑只做好一件事 开放封闭原则(对扩展开放,对修改封闭):如果新增需求,扩展 then
设计模式分类 单例模式 单例模式两个条件:
实例:
全局对象如 window、global 等
例如 Vue 也作为单例
弹窗组件,当需要时创建,关闭时缓存,再次调用时重复打开,而不是重新创建,徒损性能。
遇到的坑:
布局包、amis 包,依赖权限包,权限包请求并保存了权限 code。但是布局包的权限包与实际权限包版本号不统一,生成了两个实例。peerDependncy
策略模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const strategy = { S : function (salary ) { return salary * 4 }, A : function (salary ) { return salary * 3 }, B : function (salary ) { return salary * 2 }, } const calculateBonus = function (level, salary ) { return strategy[level](salary) } calculateBonus ('A' , 10000 )
代理模式
为一个对象提供一个代用品或占位符,以便控制对它的访问。
场景:
Proxy 或者 Object.defineProperty
迭代器模式
提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象的内部表示。
实例:
Array.prototype.forEach
ES6 Iterator
发布-订阅模式 & 观察者模式 定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使它们能够自动更新自己,当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
发布订阅模式与观察者模式都是感知变化,相应变化。区别在于有没有中间人。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Subject { constructor ( ) { this .state = 0 this .observers = [] } getState ( ) { return this .state } setState (state ) { this .state = state this .notifyAllObservers () } notifyAllObservers ( ) { 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 s = new Subject ()let o1 = new Observer ('o1' , s)let o2 = new Observer ('02' , s)s.setState (12 )
实例化的时候把自己注册到订阅中心(主题)。订阅中心发生变动时,通知所有观察者更新自身。
场景:
1 2 3 4 document .body .addEventListener ('click' , function ( ) { console .log ('hello world!' ) }) document .body .click ()
Vue 响应式
IntersectionObserver 监听元素状态
组合模式
将对象组合成树形结构,以表示“整体-部分”的层次结构。
通过对象的多态表现,使得用户对单个对象和组合对象的使用具有一致性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TrainOrder { create ( ) { console .log ('创建火车票订单' ) } } class HotelOrder { create ( ) { console .log ('创建酒店订单' ) } } class TotalOrder { constructor ( ) { this .orderList = [] } addOrder (order ) { this .orderList .push (order) return this } create ( ) { this .orderList .forEach ((item ) => { item.create () }) return this } } let train = new TrainOrder ()let hotel = new HotelOrder ()let total = new TotalOrder ()total.addOrder (train).addOrder (hotel).create ()
享元模式
职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Action { constructor (name ) { this .name = name this .nextAction = null } setNextAction (action ) { this .nextAction = action } handle ( ) { console .log (`${this .name} 审批` ) if (this .nextAction != null ) { this .nextAction .handle () } } } let a1 = new Action ('组长' )let a2 = new Action ('经理' )let a3 = new Action ('总监' )a1.setNextAction (a2) a2.setNextAction (a3) a1.handle ()
场景:
中介者模式
解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的 相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知 中介者对象即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class A { constructor ( ) { this .number = 0 } setNumber (num, m ) { this .number = num if (m) { m.setB () } } } class B { constructor ( ) { this .number = 0 } setNumber (num, m ) { this .number = num if (m) { m.setA () } } } class Mediator { constructor (a, b ) { this .a = a this .b = b } setA ( ) { let number = this .b .number this .a .setNumber (number * 10 ) } setB ( ) { let number = this .a .number this .b .setNumber (number / 10 ) } } let a = new A ()let b = new B ()let m = new Mediator (a, b)a.setNumber (10 , m) console .log (a.number , b.number )b.setNumber (10 , m) console .log (a.number , b.number )
装饰者模式
适配者模式
将一个类的接口转化为另外一个接口,以满足用户需求,使类之间接口不兼容问题通过适配器得以解决。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Plug { getName ( ) { return 'iphone充电头' } } class Target { constructor ( ) { this .plug = new Plug () } getName ( ) { return this .plug .getName () + ' 适配器Type-c充电头' } } let target = new Target ()target.getName ()
场景:
版权声明: 本博客所有文章除特别声明外,均采用
CC BY 4.0 CN协议
许可协议。转载请注明出处!
Жизнь, как качели - то вверх, то вниз.