【JavaScript】设计模式(单例、策略、发布-订阅)
创始人
2024-05-23 11:18:40
0

💻 【JavaScript】设计模式(单例、策略、发布-订阅) 🏠专栏:JavaScript
👀个人主页:繁星学编程🍁
🧑个人简介:一个不断提高自我的平凡人🚀
🔊分享方向:目前主攻前端,其他知识也会阶段性分享🍀
👊格言:☀️没有走不通的路,只有不敢走的人!☀️
👉让我们一起进步,一起成为更好的自己!!!🎁

文章目录

  • 【JavaScript】设计模式
    • 一. 单例模式
      • (1) 概念
      • (2) 场景
      • (3) 案例:书写一个弹窗
    • 二. 策略模式
      • (1) 概念
      • (2) 场景
      • (3) 案例
      • (4) 优缺点
    • 三. 发布-订阅模式
      • (1) 什么是发布-订阅模式
        • 1. 定义
        • 2. 例子
      • (2) 如何实现发布-订阅模式?
        • 1. 实现思路
        • 2. 具体简单实现例子2:到书店买书
      • (3) 优缺点

【JavaScript】设计模式

一. 单例模式

(1) 概念

单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式核心:实例化一个类的时候

先判断,之前有没有实例化过

  • 如果有,就用之前的
  • 如果没有,就实例化一个新的

单例模式优点:创建对象和管理单例的职责被分布在两个不同的方法中

(2) 场景

单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 window 对象等。

在 JavaScript 开发中,单例模式的用途同样非常广泛。试想一下,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。

(3) 案例:书写一个弹窗

/*分析:
找到一个变量,初始化的时候是null 
第一次实例化后,给这个变量赋值
第二次想要实例化的时候,先去看看这个变量有没有值,如果有,就用之前的
// 一个弹窗的构造函数
class Dialog {constructor(title) {this.title = titlethis.div = document.createElement('div')this.div.style.backgroundColor = 'pink'document.body.appendChild(this.div)}changeTile(title) {this.title = titlethis.div.innerHTML = this.title}
}
// 单例模式代码
// 为了避免instance这个变量污染 改成闭包
const singleton = (function () {// 提前设置一个变量,用来记录该构造函数有没有实例化过let instance = nullreturn function (title) {// 判断构造函数有没有实例化过 // 没有实例化过if (!instance) {instance = new Dialog(title)}// 如果有,就返回这个实例化对象return instance}
})()
// 创建弹窗对象
const res = singleton('hello')
res.changeTile('小花')// 再次创建弹窗对象
const res1 = singleton('你好')
res1.changeTile('你好')
console.log(res1); // Dialog {title: '你好', div: div}

二. 策略模式

(1) 概念

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

策略模式的目的是:将算法的使用与算法的实现分离开来。

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体 的算法,并负责具体的计算过程。 第二个部分是环境类Context,Context 接受客户的请求,随后 把请求委托给某一个策略类。要做到这点,说明 Context中要维持对某个策略对象的引用。

(2) 场景

从定义上看,策略模式就是用来封装算法的。但如果把策略模式仅仅用来封装算法,未免有一点大材小用。在实际开发中,我们通常会把算法的含义扩散开来,使策略模式也可以用来封装 一系列的“业务规则”。只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以 用策略模式来封装它们。

(3) 案例

/* 例子  已知一个商品总价 500根据折扣计算实际价格例如:80%  70%  1000-300   800-50
*/
// 通过闭包的形式计算折扣
const calcDiscount = (function () {let priceList = {"80%": function (total) { return (total * 0.8).toFixed(2) },"70%": function (total) { return (total * 0.7).toFixed(2) },"50%": function (total) { return (total * 0.5).toFixed(2) }}function inner(total, type) {if (!priceList[type]) {return "折扣错误";}// 反之折扣正确,返回计算后的价格return priceList[type](total);}// 接下来根据需求定义一系列的算法// 添加折扣inner.add = function (type, fn) {priceList[type] = fn;}// 删除折扣inner.remove = function (type) {delete priceList[type];}// 修改折扣inner.change = function (type, fn) {priceList[type] = fn;}// 查看折扣inner.look = function () {return priceList;}return inner;
})()// 测试算法
// 1.计算价格
// const res = calcDiscount(1400, "80%");
// console.log(res); // 1120.00// 2.添加折扣
// calcDiscount.add("40%", function (total) { return (total * 0.4).toFixed(2) });
// const res = calcDiscount(1500, "40%")
// console.log(res); // 600// 3.删除折扣
// calcDiscount.remove("80%");
// const res = calcDiscount(1200, "80%");
// console.log(res); // 折扣错误  // 4.修改折扣
calcDiscount.change("70%", function (total) { return (total * 0.4).toFixed(2) });
const res = calcDiscount(1200, "70%");
console.log(res); // 480.00// 5.查看折扣
// console.log(calcDiscount.look()); // {80%: ƒ, 70%: ƒ, 50%: ƒ}

(4) 优缺点

优点

  • 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
  • 策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的策略中,使得它们易于切换,易于理解,易于扩展。
  • 策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。
  • 在策略模式中利用组合和委托来让环境类拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

缺点

  • 增加许多策略类或者策略对象,但实际上这比把它们负责的 逻辑堆砌在环境类中要好。
  • 要使用策略模式,必须了解所有的策略,必须了解各个策略之间的不同点, 这样才能选择一个合适的策略。

三. 发布-订阅模式

(1) 什么是发布-订阅模式

1. 定义

发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。

订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

2. 例子

例子1:比如我们很喜欢看某个公众号号的文章,但是我们不知道什么时候发布新文章,要不定时的去翻阅;这时候,我们可以关注该公众号,当有文章推送时,会有消息及时通知我们文章更新了。

上面一个看似简单的操作,其实是一个典型的发布订阅模式,公众号属于发布者,用户属于订阅者;用户将订阅公众号的事件注册到调度中心,公众号作为发布者,当有新文章发布时,公众号发布该事件到调度中心,调度中心会及时发消息告知用户。

例子2:一个卖书的例子,当你去买书的时候,如果当时有你要买的书,可以直接买到当时当书店没有这本书的时候,你就需要先在书店预订,让老板等书到了通知你,而如果你等待的时候突然又不想买了你可以告诉老板你不要了。

在上述案例中,老板就是发布者,买者就是订阅者,不想要了就是取消订阅。

(2) 如何实现发布-订阅模式?

1. 实现思路

  • 创建一个对象
  • 在该对象上创建一个缓存列表(调度中心)
  • add方法用来把函数 fn 都加到缓存列表中(订阅者注册事件到调度中心)
  • emit 方法取到 arguments 里第一个当做 event,根据 event 值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理代码)
  • remove 方法可以根据 event 值取消订阅(取消订阅)

2. 具体简单实现例子2:到书店买书

class Subscribe {constructor() {// 登记本:存放书籍和操作方法this.message = {};}// 添加订阅消息add(type, fn) {// type:订阅的书籍// fn:书籍到货后的方法// 添加前,判断登记本上是否已经存在这本书籍if (!this.message[type]) {// 如果不存在,设置一个空数组this.message[type] = [];}// 如果存在,不重复登记if (this.message[type].indexOf(fn) !== -1) { return }// 正常登记,添加对应的书籍数据this.message[type].push(fn);console.log(this.message);}// 所需的书籍到货,发布通知emit(type) {// 如果还没有这本书籍if (!this.message[type]) { return }// 如果书籍到货,通知所有想要这本书籍的人this.message[type].forEach(item => item());}// 取消订阅remove(type, fn) {// 如果没有对应的订阅消息if (!this.message[type]) { return }// 取消该书籍所有的订阅消息if (!fn) {delete this.message[type];return;}// 取消对应的订阅消息this.message[type] = this.message[type].filter(item => item !== fn);}
}
// 设置一个卖书的老板
const zs = new Subscribe();
// 进行操作
function fn1() {console.log("小王需要一本");
}
function fn2() {console.log("小张需要一本");
}
// 订阅
zs.add("西游记", fn1); // {西游记: Array(1)}
zs.add("西游记", fn2); // {西游记: Array(2)}
zs.add("三国演义", fn2); // {西游记: Array(2), 三国演义: Array(1)}
// 发布
zs.emit("西游记"); // 小王需要一本 小张需要一本
zs.emit("红楼梦");
// 取消订阅
zs.remove("西游记", fn1); // {西游记: Array(1), 三国演义: Array(1)}
zs.remove("红楼梦");

(3) 优缺点

  1. 优点
    • 对象之间解耦
    • 异步编程中,可以更松耦合的代码编写
  2. 缺点
    • 创建订阅者本身要消耗一定的时间和内存
    • 虽然可以弱化对象之间的联系,多个发布者和订阅者嵌套一起的时候,程序难以跟踪维护

结束语

希望对您有一点点帮助,如有错误欢迎小伙伴指正。
👍点赞:您的赞赏是我前进的动力!
⭐收藏:您的支持我是创作的源泉!
✍评论:您的建议是我改进的良药!
一起加油!!!💪💪💪

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...