标签:系统 设计 spi ini 重用 inner init child 结构
一个模式就是一个可重用的方案。当代码是建立在行之有效的模式上时,我们可以花更少的时间去关心我们的代码结构,从而能花更多的时间关注我们的解决方案的整体质量。
本文将简略通俗地,向大家说明常见的三大 JavaScript 设计模式:单例模式、组合模式、观察者模式
单例模式:限制一个类只能有一个实例化对象
也就是说,一个构造函数一生只能有一个实例化对象。
就像二胎政策之前的计划生育一样,夫妻双方(构造函数)一生只能有一个孩子(实例化对象)
var Parents = (function () { // 夫妻双方(构造函数) function Parents() { this.date = ‘出生时间:‘ + new Date(); this.father = ‘父亲:XXX‘; this.mather = ‘母亲:XXX‘; this.palce = ‘出生地:XXX‘; } Parents.prototype.hospital = function () {}; var instance = null; function singleton() { if (!instance) { //如果没有实例化一个对象的话,就实例一个new Parents() instance = new Parents(); } return instance } //如果已经实例化一个对象的话,直接返回之前已经实例化的对象 return singleton })() //实例化对象 var child1 = new Parents() // 相当于在执行 singleton 函数, 第一次的时候会得到一个 Parents 的实例 var child2 = new Parents() // 相当于在执行 singleton 函数, 第二次的时候, 依旧得到第一次的实例 console.log(child1 === child2) // true也就是两次实例化对象都指向同一个地址
组合模式:又叫 “部分整体” 模式,将对象组合成树形结构,以表示 “部分-整体” 的层次结构。用包含多个部件的对象组合成单一实体,这个单一实体将用作所有这些部件的访问点
平时我们在使用计算机的时候就经常遇见组合模式,当删除计算机中某个文件夹的时候,也就意味着会删除该文件夹内的所有内容。通过操作删除文件夹(单一实体)的步骤,你就能达到想要删除该文件夹内的所有内容(多个部件的对象)的目的
// 多个部件的对象 // 第一个构造函数 class Play { constructor(){}; init(){ console.log(‘game begin‘); this.gameA(); this.gameB(); this.gameC(); }; gameA(){}; gameB(){}; gameC(){}; } // 第二个构造函数 class Eat{ constructor(){}; init(){ console.log(‘eat dinner‘); } } // 第三个构造函数 class Sleep{ constructor(){}; init(){ console.log(‘go to sleep‘); } } // 单一实体 class Compose{ constructor(){ // 用来承载每一个实例的数组 this.composeArr=[]; } add(instance){ //多个部件的对象 放入 单一实体 this.composeArr.push(instance); } init(){ //console.log(‘执行单一实体‘); // 把数组里面的每一个内容调用了 this.composeArr.forEach(item => item.init()) } } let oCompose = new Compose(); // 每一次执行 add 方法就是向 oCompose 上添加内容 oCompose.add(new Play()); oCompose.add(new Eat()); oCompose.add(new Sleep()); // oCompose 里面的每一个构造函数就同时调用了 oCompose.init(); console.log(oCompose);
发布/订阅 模式:系统中的对象可以在关注的事件发生的时候给其他对象发送消息,也可以被其他对象所通知。多用于注册和接受由发布者广播的相关通知。
发布/订阅 角度,分成三个状态:订阅,取消订阅,发布
简单来说就是我们平时玩的微博:关注博主(订阅),取消关注(取消订阅),关注博主的用户收到博主发布新微博的提醒(发布)
class Observer { constructor () { // 准备的一个微信公众号 this.message = {} } // 关注公众号(订阅) on (type, fn) { // 向消息盒子里面添加成员 // type 事件类型(你要订阅的类型) // fn 事件处理函数(你要给这个类型订阅一个什么行为) if (!this.message[type]) { // 表示 this.message 里面没有这个成员 this.message[type] = [] } this.message[type].push(fn) } // 取消关注公众号(取消订阅) off (type, fn) { // 删除消息盒子里面的某一个成员 // type 是你要取消的事件类型 // fn 是你要取消的事件处理函数 if (!this.message[type]) return // 能执行到这里, 表示 this.message[type] 是一个数组 // 取消这个数组里面和 fn 一样的那个事件处理函数 // 使用过滤器 filter 方法 this.message[type] = this.message[type].filter(item => item !== fn) } // 微信粉丝发布的信息 emit (type, ...arg) { // 执行消息盒子里面的某一个对应的处理函数 // type 就是你要触发的事件类型 // 判断你有没有订阅过, 如果没有订阅过, 直接return if (!this.message[type]) return // console.log(arg) // arg 是发布的文章 var event = { // 文章标题 data: arg } // 调用每一个事件处理函数的时候, 都给你带上一个事件对象 // 如果你订阅过, 那么就执行一下 this.message[type].forEach(item => item(event)) } } var o = new Observer() // 粉丝 A B C D E 订阅公众号 o.on(‘click‘, handlerA) o.on(‘click‘, handlerB) o.on(‘click‘, handlerC) o.on(‘click‘, handlerD) o.on(‘click‘, handlerE) // 粉丝 A 取消订阅 o.off(‘click‘, handlerA) // 公众号发布文章,粉丝 B C D E 收到 o.emit(‘click‘, ‘文章一‘,‘文章二‘,‘文章三‘) // 发布事件 // 把你订阅好的事件处理函数都给你触发了 // console.log(o) // 粉丝 A B C D E // e 接收公众号发布的文章 function handlerA(e) { console.log(‘粉丝A‘, e) } function handlerB(e) { console.log(‘粉丝B‘, e) } function handlerC(e) { console.log(‘粉丝C‘, e) } function handlerD(e) { console.log(‘粉丝D‘, e) } function handlerE(e) { console.log(‘粉丝E‘, e) }
标签:系统 设计 spi ini 重用 inner init child 结构
原文地址:https://www.cnblogs.com/Welin/p/12345452.html