当前位置: 首页 > news >正文

手写JavaScript常见5种设计模式

想分享的几种设计模式

目前模式:工厂模式,单例模式,适配器模式,装饰者模式,建造者模式

建造者模式

简介:建造者模式(builder pattern)比较简单,它属于创建型模式的一种。

白话:4个部分:有个产品,有个工厂可以造产品,有个设计师指挥造多少,有个人想买产品。

买产品的用户不介意产品制造流程,只需要产品!

function Cola() {this.sugar = '50g',this.water = '100g'
}
function Packing() { // 第一种打包方式this.createPkg = function(){console.log('创建可乐外皮')}this.pushCola = function() {console.log('可乐倒进瓶子')}this.complete = function() {var cola = new Cola()cola.complete = truereturn cola}this.init = function() {this.createPkg() // 创建外皮this.pushCola() // 倒进瓶子//还可以增加其他步骤return this.complete() // 制作完成}
}
function greenPacking() { //绿皮可乐打包方式this.createPkg = function(){console.log('创建green可乐外皮')}this.pushCola = function() {console.log('可乐倒进green瓶子')}this.complete = function() {var cola = new Cola()cola.complete = truereturn cola}this.init = function() {this.createPkg() // 创建外皮this.pushCola() // 倒进瓶子//还可以增加其他步骤return this.complete() // 制作完成}
}
function Boss() {this.createCola = function(packType) {const pack = new window[packType]this.product = pack.init() //完整产品产出}this.getCola = function(packType) {this.createCola(packType);return this.product}
}
const boss = new Boss()
var UserCola = boss.getCola('greenPacking') // UserCola.complete === true

参考 前端进阶面试题详细解答

其他东西都不要,只要最后生产好的Cola,有sugar,有water。

关键在于Boss 函数中,担任一个整合的职责

同样的Boss函数,我可以通过更换Packing函数,打包方式,获得不同样式的Cola。

通过给getCola函数传入不同想要的参数,获得不同的最终产品。实现了可插拔的函数结构。

装饰者模式

装饰者提供比继承更有弹性的替代方案。 装饰者用用于包装同接口的对象,不仅允许你向方法添加行为,而且还可以将方法设置成原始对象调用(例如装饰者的构造函数)。

装饰者用于通过重载方法的形式添加新功能,该模式可以在被装饰者前面或者后面加上自己的行为以达到特定的目的。

好处:

装饰者是一种实现继承的替代方案。当脚本运行时,在子类中增加行为会影响原有类所有的实例,而装饰者却不然。取而代之的是它能给不同对象各自添加新行为

function iwatch () {this.battery = 100;this.getBattery = function() {console.log(this.battery)}
}iwatch.prototype.getNewPart = function(part) {this[part].prototype = this; //把this对象上的属性 指向 新对象的prototypereturn new this[part]; //返回一个新对象,不修改原对象,新增了新对象的属性
}iwatch.prototype.addNetwork = function() {this.network = function() {console.log('network')}
}iwatch.prototype.addSwim = function() {this.swim = function() {console.log('swim')}
}var watch = new iwatch();
watch.getBattery(); // 100watch = watch.getNewPart('addNetwork'); // 添加新行为,network()
watch = watch.getNewPart('addSwim'); // 既有network方法,也有swim方法

在 ES7 中引入了@decorator 修饰器的提案,参考阮一峰的文章。

@testable
class MyTestableClass {// ...
}function testable(target) {target.isTestable = true;
}MyTestableClass.isTestable // true

直接可以使用,装饰器行为

@decorator
class A {}// 等同于class A {}
A = decorator(A) || A;

工厂模式

一个工厂能生产好多不同的产品,最常见的工厂函数就是jQ的$()函数,每一个函数的结果都是一个需要的产品。

function Product(name) {this.name = name;
}
Product.prototype.init = function () {console.log('init');
}
Product.prototype.go = function () {console.log('go');
}function Factory () {
}
Factory.prototype.add = function(name) {return new Product(name);
}//use
let f = new Factory();
let a = f.add('a');console.log(a.name);
a.init();
a.go();

适配器模式

Adapter,将一个类(对象)的接口(方法或者属性)转化为另一个接口,以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决

function Person () {
}
Person.prototype.Say = function() {throw new Error("该方法必须被重写!")
}
Person.prototype.Walk = function() {throw new Error("该方法必须被重写!")
}function Dog () {
}
Dog.prototype.Walk = function() {throw new Error("该方法必须被重写!")
}
Dog.prototype.shout = function() {throw new Error("该方法必须被重写!")
}function PersonA () {Person.apply(this)
}
PersonA.prototype = new Person()
PersonA.prototype.Say = function() {console.log('Person say')
}
PersonA.prototype.Walk = function() {console.log('Person Walk')
}function DogBlack () {Dog.apply(this)
}
DogBlack.prototype = new Dog()
DogBlack.prototype.Walk = function() {console.log('Dog Walk')
}
DogBlack.prototype.shout = function() {console.log('Dog Shout')
}//现在希望Dog类也可以学会Say,并且多走几步function DogSayAdapter (DogClass) {Dog.apply(this)this.DogClass = DogClass
}
DogSayAdapter.prototype = new Dog()
DogSayAdapter.prototype.Say = function() {this.DogClass.shout()
}
DogSayAdapter.prototype.Walk = function() {this.DogClass.Walk()this.DogClass.Walk()
}var personA = new PersonA()
var dogBlack = new DogBlack()
var dogSay = new DogSayAdapter(dogBlack)personA.Say()
personA.Walk()
dogBlack.Walk()
dogBlack.shout()dogSay.Say()
dogSay.Walk()//walk * 2    

适配器不只是函数接口,还有数据格式的适配

在前后端数据传递时,常用到适配器模式,也就是通俗易懂的格式化数据,format函数等等

vue的computed计算属性也是适配器模式的一种实现

const originData = [{title: 'title',age: 18,content: ['123',321],callback: function(){console.log(this)}},{title: 'title2',age: 1,content: ['1',3],callback: function(){console.log('title2')}}
]function dataAdapter(data) {return data.map(item => {return {title: item.title,content: item.content.join(','),init: item.callback}})
}var formatData = dataAdapter(originData)

e.g:原始data 的数据不满足当前的要求,通过适配器,把数据格式化成想要的格式,对原始数据没有改变

单例模式

function Simple (name) {this.name = name
}
Simple.prototype.go = function() {this.name = 'go'console.log(this.name)
}//static静态方法
Simple.getInstance = (function() {var insreturn function(name){if (!ins) {ins = new Simple(name)}return ins}
})()let a = Simple.getInstance('a') // name: a
let b = Simple.getInstance('b') // name: ab===a//true

非单例模式下,相同的new Simple()构造函数,不相等。

通过闭包只创建一次Simple实例,大家公用一个。

惰性单例模式

惰性和懒加载lazyload相似,延迟加载,或者说需要时再加载,不然一次加载过多,频繁进行操作dom影响性能

尽管上述代码有Simple.getInstance方法,可以在需要时再进行实例化,但仍然不是一个好的实现方式。

可以将惰性加载的部分提取出来。

e.g:

var simple = function(fn) {var instance;return function() {return instance || (instance = fn.apply(this, arguments));}
};
// 创建遮罩层
var createMask = function(){// 创建div元素var mask = document.createElement('div');// 设置样式mask.style.position = 'fixed';mask.style.top = '0';......document.body.appendChild(mask);// 单击隐藏遮罩层mask.onclick = function(){this.style.display = 'none';}return mask;
};// 创建登陆窗口
var createLogin = function() {// 创建div元素var login = document.createElement('div');// 设置样式login.style.position = 'fixed';login.style.top = '50%';......login.innerHTML = 'login it';document.body.appendChild(login);return login;
};document.getElementById('btn').onclick = function() {var oMask = simple(createMask)();oMask.style.display = 'block';var oLogin = simple(createLogin)();oLogin.style.display = 'block';
}

总结

对五种常见常用的设计模式进行了学习,这几种很多时候都会用到,接下来还会继续学习其他的18种设计模式,可能有的设计模式不一定在实际敲码中使用,学了没坏处,总能用得上嗷!

网上对于设计模式的文章,书籍层出不尽,但看得再多,不如自己理解,并且实际使用。很多时候是几种设计模式融合在一起使用,如果不是自己去写一遍,理解一遍,可能常见的设计模式都理解不了。这样就太可惜了,发现干净整洁的代码,都说不出哪里好,就是看着舒服,顺眼,运行速度快…

相关文章:

手写JavaScript常见5种设计模式

想分享的几种设计模式 目前模式:工厂模式,单例模式,适配器模式,装饰者模式,建造者模式 建造者模式 简介:建造者模式(builder pattern)比较简单,它属于创建型模式的一种…...

Python 异步: 当前和正在运行的任务(9)

我们可以反省在 asyncio 事件循环中运行的任务。这可以通过为当前运行的任务和所有正在运行的任务获取一个 asyncio.Task 对象来实现。 1. 如何获取当前任务 我们可以通过 asyncio.current_task() 函数获取当前任务。此函数将为当前正在运行的任务返回一个任务对象。 ... # …...

REDIS-雪崩、击穿、穿透

直接发车🚗 一.雪崩 1.触发原因 A.大量缓存数据在同一时间过期(失效) B.redis故障宕机 上述均导致全部请求去访问数据库,导致DB压力骤增,严重则导致数据库宕机/系统宕机 2.应对策略 不同触发原因,应对策略也不一致 应对A&a…...

什么人合适学习Python

发了几天的Python基础,也认识了一些朋友,忽然有人问起,说为啥学Python,或者说啥人学习Python,作为一个教龄8年从Python一线讲师到Python教学主管的我和大家分享一下个人的看法,还是提前说一下,个…...

greenDao的使用文档

介绍:greenDAO 是一款轻量级的 Android ORM 框架,将 Java 对象映射到 SQLite 数据库中,我们操作数据库的时候,不在需要编写复杂的 SQL语句, 在性能方面,greenDAO 针对 Android 进行了高度优化, …...

基于JAVA+SpringBoot+LayUI+Shiro的仓库管理系统

基于JAVASpringBootLayUIShiro的仓库管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项…...

金三银四面试必看,复盘字节测试开发面试:一次测试负责人岗位面试总结

最近面试了某企业的测试负责人岗位,历经四面,收获蛮多的。 这篇文章,我想聊聊这次面试过程中的一些经历,以及些许经验和教训。 岗位要求 岗位名称:测试负责人 岗位要求:1、扎实的技术以及丰富的技术项目…...

【算法自由之路】 贪心算法

贪心算法 局部最右得到全局最右难点在于如何证明局部最优可以得到全局最优堆 和 排序 是贪心算法最常用的实现算法 贪心算法作为最符合自然智慧的算法,思路是从小部分取最优从而获得最终的最优,但是难得是怎样获取部分最优才能得到全局最优。 有时候我…...

Scratch少儿编程案例-水果忍者-学生作业

专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

7.Docker Compose

Docker Compose 介绍 Docker Compose是Docker官方编排(Orchestration)项目之一,负责快速的部署分布式应用。其代码目前在https://github.com/docker/compose上开源。Compose 定位是 「定义和运行多个 Docker 容器的应用(Definin…...

GitHub访问问题与 Steam++下载及使用(适合小白)

前言 📜 “ 作者 久绊A ” 专注记录自己所整理的Java、web、sql等,IT技术干货、学习经验、面试资料、刷题记录,以及遇到的问题和解决方案,记录自己成长的点滴 ​ 目录 前言 一、Steam的介绍 1、大概介绍 2、详细介绍 二、Ste…...

Oracle对象——视图之简单视图与视图约束

文章目录什么是视图为什么会使用视图视图语法案例简单视图的创建更改数据基表,视图数据会变化么?更改视图数据,基表数据会变更么?带检查约束的视图结论创建只读视图(MySQL不支持)总结什么是视图 视图是一种…...

SAP模块常用增强总结

MM模块: 采购订单增强: BADI :ME_GUI_PO_CUST ME_PROCESS_PO_CUST 物料凭证增强: BADI:MB_DOCUMENT_BADI USER-EXIT:MBCF0002 实现功能1、当参照预留过帐时,检查填入数量是否小于预留数量 2…...

当make执行遇到 Arguments too long

1. 问题 Ubuntu20.04上make编译生成so的时候报错: make[1]:execvp:/bin/sh:Arguments too long对应makefile中的报错位置,仅仅是生成so的时候报错,伪代码如下 ${build_tool} -shared -fpic -o "$" ${OBJ_FILE} ${LDFLAGS}然而如…...

《手把手教你》系列基础篇(七十三)-java+ selenium自动化测试-框架设计基础-TestNG实现启动不同浏览器(详解教程)

1.简介 上一篇文章中,从TestNg的特点我们知道支持变量,那么我们这一篇就通过变量参数来启动不同的浏览器进行自动化测试。那么如何实现同时启动不同的浏览器对脚本进行测试,且听我娓娓道来。 2.项目实战 2.1创建一个TestNg class 1.首先按…...

Maven基础

Maven简介 传统项目: jar包不统一 不兼容 项目中有部分jar包会升级 没升级的部分会起冲突 管理复杂 Maven本质是一个项目管理工具 pom POM Project Object Model 项目对象模型 把项目以对象形式进行管理 先写 pom.xml 的配置文件 代表一个项目 1个项目对应1个po…...

C++入门:初识类和对象

C入门:类和对象1 本节目录C入门:类和对象11.auto关键字(C11)1.1类型别名思考1.2auto简介typeid运算符:获取类型信息1.3 auto的使用细则1.4auto不能推到的场景2.基于范围的for循环(C11)2.1范围for的语法2.2范围for的使用条件3.指针…...

BERT在CNN上也能用?看看这篇ICLR Spotlight论文丨已开源

如何在卷积神经网络上运行 BERT?你可以直接用 SparK —— 字节跳动技术团队提出的提出的稀疏层次化掩码建模 ( Designing BERT for Convolutional Networks: Sparse and Hierarchical Masked Modeling ),近期已被人工智能顶会 ICLR 2023 收录为 Spotligh…...

【MFC】模拟采集系统——界面设计(17)

功能介绍 启动界面 开始采集: PS:不涉及 数据保存,重现等功能 界面设计 界面分为三块:顶部黑条带关闭按钮、左边对话框,右边的主界面 资源: 顶部黑条 top.bmp 2* 29 (宽 * 高 像素点&…...

锐捷(十五)mpls vxn跨域optionc场景

一 实验拓扑二 实验需求ce1和ce2为两个分公司,要求两个分公司之间用mpls vxn 进行通信,组网方式是optionc。三 实验分析optionc在转发平面上有点难理解,有一些关键点需要注意,大家点击链接可以参考我上篇发过的一个文章&#xff1…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...