你值得关注的几种常见的js设计模式
前言
潜水了一段时间,今天空闲时间复盘下之前的知识点,聊聊 js 几种常见的设计模式。
掌握 JavaScript 中常见的一些设计模式,对我们书写规范性代码,可维护性代码有很大的帮助。
ps:最近在一些好友的鼓励下,pubdreamcc 准备着手经营一个公众号了,具体信息会在接下来的两天时间内发布,新手上路,欢迎大伙提供一些宝贵的建议,cc 在这里先谢了~
内容主体
单例模式
所谓单例模式即为:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
这里其实利用的是 js闭包 来实现这样的功能。
假如现在我们有这样的需求,设置一个管理员,无论创建多次都只是设置一次。
function SetManager(name) {
this.manager = name;
}
SetManager.prototype.getName = function() {
console.log(this.manager);
};
var SingletonSetManager = (function() {
var manager = null;
return function(name) {
if (!manager) {
manager = new SetManager(name);
}
return manager;
}
})();
SingletonSetManager('a').getName(); // a
SingletonSetManager('b').getName(); // a
SingletonSetManager('c').getName(); // a
这种方法有一个缺点就是:如果我们需要再次创建一个 HR,则需要将代码再复制一遍,所以我们可以提取通用的单例。
function getSingleton(fn) {
var instance = null;
return function() {
if (!instance) {
instance = fn.apply(this, arguments);
}
return instance;
}
}
// 设置管理员
var managerSingleton = getSingleton(function(name){
var manager = new SetManager(name);
return manager;
})
managerSingleton('a').getName(); // a
managerSingleton('b').getName(); // a
managerSingleton('c').getName(); // a
// 设置 HR
function SetHr(name) {
this.hr = name;
}
SetHr.prototype.getName = function() {
console.log(this.hr);
};
var hrSingleton = getSingleton(function(name) {
var hr = new SetHr(name);
return hr;
});
hrSingleton('aa').getName(); // aa
hrSingleton('bb').getName(); // aa
hrSingleton('cc').getName(); // aa
这样我们的代码可通用性就会变得更好,省去了一些重复性的代码。
代理模式
所谓代理模式就是:我们不方便直接访问某个对象时,可以为对象创建一个占位符(代理),以便控制对它的访问,我们实际上访问的是代理对象。
这里我们以一个过滤敏感字符来说明这种模式
// 主体,发送消息
function sendMsg(msg) {
console.log(msg);
}
// 代理,对消息进行过滤
function proxySendMsg(msg) {
// 无消息则直接返回
if (typeof msg === 'undefined') {
console.log(null);
return;
}
// 有消息则进行过滤
msg = ('' + msg).replace(/泥\s*煤/g, '');
sendMsg(msg);
}
sendMsg('泥煤呀泥 煤呀'); // 泥煤呀泥 煤呀
proxySendMsg('泥煤呀泥 煤'); // 呀
proxySendMsg(); // null
这样操作的意图很明显,当没有消息的时候,控制对主体对象的访问,代理直接返回一个 null ,有消息,则会过滤掉敏感字符,实现虚拟代理。
策略模式
策略模式就是内部封装一些算法,它们之间可以互相替换,但是它们不随客户端变化而变化。
策略模式我们外部看不到算法的具体实现,我们也只关心算法实现的结果,不关注过程。
这里以一个商品促销的例子来说明下:在圣诞节,某些商品需要八折出售,有些商品需要九折出售,到了元旦节,普通客户满100减30,vip客户满100减50。可以看到商品出售的价格需要根据不同的条件来规定,分别采取不同的算法实现,所以我们采用策略模式。
// 价格策略对象
class PriceStrategy {
constructor() {
// 内部算法对象
this.stragtegy = {
// 100返30
return30(price) {
return +price + parseInt( price / 100) * 30;
},
// 100 返 50
return50(price) {
return +price + parseInt(price/ 100) * 50;
},
// 9 折
percent90(price) {
return price * 100 * 90 / 10000
},
percent80(price) {
return price * 100 * 80 / 10000
},
percent50(price) {
return price * 100 * 50 / 10000
}
}
}
// 策略算法调用接口
getPrice(algorithm, price) {
return this.stragtegy[algorithm] && this.stragtegy[algorithm](price);
}
}
let priceStrategy = new PriceStrategy();
let price = priceStrategy.getPrice('return50', 314.67);
console.log(price);
这样,我们可以采取不同的策略算法得到商品的不同价格。
观察者模式
观察者模式又称为 “发布-订阅模式”,通过定义一种依赖关系,当一个对象状态发生改变时,订阅者会得到通知。
其实,我们传统的 DOM 事件绑定就是一种发布-订阅模式。
// 订阅
document.body.addEventListener('click', function() {
console.log('click1');
}, false);
document.body.addEventListener('click', function() {
console.log('click2');
}, false);
// 发布
document.body.click(); // click1 click2
装饰者模式
装饰者模式就是在不改变原对象基本功能的基础上,通过增加功能使得原本对象满足用户的更为复杂的需求。
比如有这么一个需求:
用户点击输入框时,如果输入框输入的内容有限制,那么在其后面显示用户输入内容的限制格式的提示文案
---------------->>>>>>> 现在要改为:
多加一条需求,默认输入框上边显示一行文案,当用户点击输入框的时候,文案消失。
这里是以前的代码:
// 输入框元素
let telInput = document.getElementById('tel_input');
// 输入框提示文案
let telWarnText = document.getElementById('tel_warn_text');
// 点击输入框显示输入框输入格式提示文案
input.onclick = function () {
telWarnText.style.display = 'inline-block';
};
修改之后的代码:
// 输入框元素
let telInput = document.getElementById('tel_input');
// 输入框输入格式提示文案
let telWarnText = document.getElementById('tel_warn_text');
// 输入框提示输入文案
let telDemoText = document.getElementById('tel_demo_text');
// 点击输入框显示输入框输入格式提示文案
input.onclick = function () {
telWarnText.style.display = 'inline-block';
telDemoText.style.display = 'none';
};
但是紧接着悲剧就来了,修改了电话输入框,还有姓名、地址输入框等等;
装饰已有的功能对象
原有的功能已经不满足用户的需求了,此时需要做的是对原有的功能添加,设置新的属性和方法来满足新的需求,但是有不影响原来已经有的部分。
let decorator = function (input, fn) {
let getInput = document.getElementById(input);
if(typeof getInput.onclick === 'function') {
let oldClick = getInput.onclick;
getInput.onclick = function() {
// 原来的事件回调函数
oldClick();
// 新增的事件回调函数
fn();
}
} else {
getInput.onclick = fn;
}
// 其他事件
};
// 电话输入框功能装饰
decorator('tel_input', function() {
document.getElementById('tel_demo_text').sytle.display = 'none'
});
// 姓名输入框装饰
decorator('name_input', function() {
document.getElementById('name_demo_text').sytle.display = 'none'
});
// 地址输入框装饰
decorator('address_input', function() {
document.getElementById('address_demo_text').sytle.display = 'none'
});
后语
本编文章出自于我的 github 仓库 ,欢迎喜欢的伙伴 star ,谢谢 。
仓库地址 前端学习
你值得关注的几种常见的js设计模式的更多相关文章
- [转载 ]五种常见的 PHP 设计模式
五种常见的 PHP 设计模式 策略模式 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个设计模 ...
- java之 ------ 几种常见的简单设计模式
前言: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.用于解决特定环境下.反复出现的特定问题的解决方式.使用设计模式是为了可重用代码.让代 ...
- 【转】五种常见的 PHP 设计模式
工厂模式 最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合.要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程.在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完 ...
- 五种常见的 PHP 设计模式
设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma.Richard Helm.Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”).所 ...
- [转]五种常见的 PHP 设计模式
FROM : http://www.ibm.com/developerworks/cn/opensource/os-php-designptrns/ 设计模式 一书将设计模式引入软件社区,该书的作者是 ...
- 几种常见算法js
没有系统地总结过js算法,虽然在项目中陆陆续续的也用过好多算法,有一次去一家公司面试的时候,面试官说想谈谈算法,有点懵了,所以接下来的面试中谈的也有点被动,避免下次再碰到这种情况,今天决定好好的总结下 ...
- 前端教程&开发模块化/规范化/工程化/优化&工具/调试&值得关注的博客/Git&面试-资源汇总
内容精简 资源这么多,多看看多学习再总结肯定是好的.多读读就算看重了不算浪费时间,毕竟一千个读者就有一千个林黛玉,还有温故而知新,说不定多读一些内容,就发现惊喜了呢.不过,在此也精简一些内容,就1~2 ...
- Win 10更新版1709有哪些新功能值得关注!
windows 10秋季创意者更新版1709发布已经有段时间了,也有很多用户选择升级这次更新的系统.那么,这次Win 10 更新版1709有哪些新功能值得关注呢?下面,一起随主机吧来看一看吧! 1. ...
- Java中9种常见的CMS GC问题分析与解决
1. 写在前面 | 本文主要针对 Hotspot VM 中"CMS + ParNew"组合的一些使用场景进行总结.重点通过部分源码对根因进行分析以及对排查方法进行总结,排查过程会省 ...
随机推荐
- [译]Exactly once is NOT exactly the same
近日学习Pulsar文档时,注意到Pulsar提到其提供的是effectively-once语义,而不是其它流计算引擎announce的exactly-once语义,并引用了Exactly once ...
- IOS开发学习笔记007-数据结构
目录: 1.全局变量和局部变量 2.结构体 3.结构体数组 4.结构体做函数参数 5.结构体指针 6.枚举 7.总结 一.全局变量和局部变量 全局变量和局部变量的区别 1. 全局变量,再函数外定义的变 ...
- Windows网络编程笔记4 -- Winsock 协议相关知识
Win32平台上的Winsock编程,Winsock是一个与协议无关的接口.以下协议是我们需要了解的: 网络协议的特征包括: 1. 面向消息 2. 面向连接和无线接 3. 可靠性和次序性 4. ...
- windows下使用grunt
grunt官网:http://www.gruntjs.org/ 一.安装grunt 先安装node,在http://www.nodejs.org/可以下载安装包直接安装.在命令行下运行: npm in ...
- CSU-2172 买一送一
CSU-2172 买一送一 Description ICPCCamp 有 n 个商店,用 1, 2, -, n 编号.对于任意 i > 1,有从商店 \(p_i\) 到 i 的单向道路. 同时, ...
- [转]核函数K(kernel function)
1 核函数K(kernel function)定义 核函数K(kernel function)就是指K(x, y) = <f(x), f(y)>,其中x和y是n维的输入值,f(·) 是从n ...
- 【转】BehaviorDesigner学习
BehaviorDesigner学习 行为树: 行为树设计师插件是一个专门为unity设计的AI插件. 通过继承Behavior中的Task下的四个节点,可以创建自己的行为树节点. 行为树中的自定 ...
- Spring整合Hibernate与Struts
整合S2SH 一.导入jar包 Spring jar包 Hibernate jar包 Struts2 jar包 以上就是整合需要的所有jar包,当然其中有重复的包,(对比之后去掉版本低的就可以了,还有 ...
- HDU 3987 Harry Potter and the Forbidden Forest(边权放大法+最小割)
Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/ ...
- [HAOI2018][bzoj5306] 染色 [容斥原理+NTT]
题面 传送门 思路 这道题的核心在于"恰好有$k$种颜色占了恰好$s$个格子" 这些"恰好",引导我们去思考,怎么求出总的方案数呢? 分开考虑 考虑把恰好有$s ...