前言
模式是在某一背景下某个问题的一种解决方案。
设计模式(Design pattern)是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结。
为了保障代码的可靠性、进步代码的复用率、使代码更容易被保护和浏览,咱们须要理解并正当应用设计模式。
日常开发中,一些特定的场景下你的解决办法可能并不是很现实,往往这时借助一些设计模式能够让你优雅而高效的实现这些逻辑,上面就介绍一些尽管不是最全的但肯定是最罕用的设计模式。
单例模式:
定义:一个类只返回一个实例,一旦创立再次调用就间接返回。
应用场景:比方自定义弹窗,无论你程序中多少调用,都只应创立一个弹窗对象。
class CreateUser { constructor(name) { this.name = name; this.getName(); } getName() { return this.name; }};const ProxyMode = (() => { let instance = null; return (name) => { if(!instance) { instance = new CreateUser(name); } return instance; }})();let a = ProxyMode('vn');let b = ProxyMode('lb');console.log(a, b); // vn vn 单例模式只会创立一次实例
策略模式:
定义:定义一个策略类只专一与各办法算法实现,定义一个接口调用这些办法。
特点:代码优雅,可读性高。
// 策略类const levelObj = { "A": money => money * 4, "B": money => money * 3, "C": money => money * 2}// 环境类 封装调用接口const getMoney = (level, money) => levelObj[level](money);console.log(getMoney('A', 200)) // 800
代理模式:
定义:为一个对象提供一个代用品或占位符,以便管制对它的拜访。
应用场景:比方图片懒加载,先缓存动静 loading,必要时传入 src。
const imgFunc = (() => { let imgNode = document.createElement('img'); document.body.appendChild(imgNode); return { setSrc: (src) => { imgNode.src = src; } }})();const ProxyImg = (() => { let img = new Image(); img.onload = () => { let node = document.getElementsByTagName('img') imgFunc.setSrc(img.src); } return { setSrc: (src) => { imgFunc.setSrc('../C3photo/jacky/1.jpg'); img.src = src; } }})();ProxyImg.setSrc('../C3photo/jacky/2.jpg');
装璜者模式:
定义:装璜者模式可能在不扭转对象本身的根底上,在运行程序期间给对象动静地增加职责。
应用场景:相似于拦截器,增加对象的前置和后置事件等。
Function.prototype.before = function(beforefn) { let _self = this; return function () { beforefn.apply(this, arguments); return _self.apply(this, arguments); }}Function.prototype.after = function(afterfn) { let _self = this; return function(){ let ret = _self.apply(this, arguments); afterfn.apply(this, arguments); return ret; }}let func = function() { console.log('2');}//func1和func3为挂载函数let func1 = function() { console.log('1');}let func3 = function() { console.log('3');}func = func.before(func1).after(func3);func(); // 1 2 3
公布订阅模式:
定义:订阅者(Subscriber)把本人想订阅的事件注册(Subscribe)到调度核心(Event Channel),当发布者(Publisher)公布该事件(Publish Event)到调度核心,也就是该事件触发时,由调度核心对立调度(Fire Event)订阅者注册到调度核心的解决代码。
应用场景:微信公众号的订阅
let eventEmitter = { list: {}, on(event, fn) { // 订阅 let _this = this; _this.list[event] = _this.list[event] || []; _this.list[event].push(fn); return _this; }, emit() { // 公布 let _this = this; let event = [].shift.call(arguments), fns = _this.list[event]; if (fns && fns.length) { fns.forEach((fn) => fn.apply(_this, arguments)); } return _this; }, off(event, fn) { // 勾销订阅 let _this = this; let fns = _this.list[event]; if (!fns) return false; if (!fn) { fns.length = 0; } else { for (let i = 0; i < fns.length; i++) { if (fns[i] === fn || fns[i].fn === fn) { fns.splice(i, 1); break; } } } }};const user1 = (content) => { console.log("用户1订阅了:", content);};const user2 = (content) => { console.log("用户2订阅了:", content);};const user3 = (content) => { console.log("用户3订阅了:", content);};// 订阅eventEmitter.on("article1", user1);eventEmitter.on("article1", user2);eventEmitter.on("article2", user3);eventEmitter.emit("article1", "Javascript 公布-订阅模式");eventEmitter.emit("article2", "Javascript 观察者模式");eventEmitter.off("article1", user1);eventEmitter.emit("article1", "Javascript 公布-订阅模式");//用户1订阅了: Javascript 公布-订阅模式//用户2订阅了: Javascript 公布-订阅模式//用户3订阅了: Javascript 观察者模式//用户2订阅了: Javascript 公布-订阅模式
总结
学习设计模式不仅能够使咱们用好这些胜利的设计模式,更重要的是能够使咱们深刻了解面向对象的设计思维。
~
~本文完,感激浏览!
~
学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂!
大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教!
你来,怀揣冀望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!
常识与技能并重,内力和外功兼修,实践和实际两手都要抓、两手都要硬!