前言

模式是在某一背景下某个问题的一种解决方案。

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

为了保证代码的可靠性、提高代码的复用率、使代码更容易被维护和阅读,我们需要了解并合理使用设计模式。

日常开发中,一些特定的场景下你的处理方法可能并不是很理想,往往这时借助一些设计模式可以让你优雅而高效的实现这些逻辑,下面就介绍一些虽然不是最全的但一定是最常用的设计模式。

单例模式:

定义:一个类只返回一个实例,一旦创建再次调用就直接返回。

使用场景:比如自定义弹窗,无论你程序中多少调用,都只应创建一个弹窗对象。

  1. class CreateUser {
  2. constructor(name) {
  3. this.name = name;
  4. this.getName();
  5. }
  6. getName() {
  7. return this.name;
  8. }
  9. };
  10. const ProxyMode = (() => {
  11. let instance = null;
  12. return (name) => {
  13. if(!instance) {
  14. instance = new CreateUser(name);
  15. }
  16. return instance;
  17. }
  18. })();
  19. let a = ProxyMode('vn');
  20. let b = ProxyMode('lb');
  21. console.log(a, b); // vn vn 单例模式只会创建一次实例

策略模式:

定义:定义一个策略类只专注与各方法算法实现,定义一个接口调用这些方法。

特点:代码优雅,可读性高。

  1. // 策略类
  2. const levelObj = {
  3. "A": money => money * 4,
  4. "B": money => money * 3,
  5. "C": money => money * 2
  6. }
  7. // 环境类 封装调用接口
  8. const getMoney = (level, money) => levelObj[level](money);
  9. console.log(getMoney('A', 200)) // 800

代理模式:

定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。

使用场景:比如图片懒加载,先缓存动态 loading,必要时传入 src。

  1. const imgFunc = (() => {
  2. let imgNode = document.createElement('img');
  3. document.body.appendChild(imgNode);
  4. return {
  5. setSrc: (src) => {
  6. imgNode.src = src;
  7. }
  8. }
  9. })();
  10. const ProxyImg = (() => {
  11. let img = new Image();
  12. img.onload = () => {
  13. let node = document.getElementsByTagName('img')
  14. imgFunc.setSrc(img.src);
  15. }
  16. return {
  17. setSrc: (src) => {
  18. imgFunc.setSrc('../C3photo/jacky/1.jpg');
  19. img.src = src;
  20. }
  21. }
  22. })();
  23. ProxyImg.setSrc('../C3photo/jacky/2.jpg');

装饰者模式:

定义:装饰者模式能够在不改变对象自身的基础上,在运行程序期间给对象动态地添加职责。

使用场景:类似于拦截器,添加对象的前置和后置事件等。

  1. Function.prototype.before = function(beforefn) {
  2. let _self = this;
  3. return function () {
  4. beforefn.apply(this, arguments);
  5. return _self.apply(this, arguments);
  6. }
  7. }
  8. Function.prototype.after = function(afterfn) {
  9. let _self = this;
  10. return function(){
  11. let ret = _self.apply(this, arguments);
  12. afterfn.apply(this, arguments);
  13. return ret;
  14. }
  15. }
  16. let func = function() {
  17. console.log('2');
  18. }
  19. //func1和func3为挂载函数
  20. let func1 = function() {
  21. console.log('1');
  22. }
  23. let func3 = function() {
  24. console.log('3');
  25. }
  26. func = func.before(func1).after(func3);
  27. func(); // 1 2 3

发布订阅模式:

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

使用场景:微信公众号的订阅

  1. let eventEmitter = {
  2. list: {},
  3. on(event, fn) {
  4. // 订阅
  5. let _this = this;
  6. _this.list[event] = _this.list[event] || [];
  7. _this.list[event].push(fn);
  8. return _this;
  9. },
  10. emit() {
  11. // 发布
  12. let _this = this;
  13. let event = [].shift.call(arguments),
  14. fns = _this.list[event];
  15. if (fns && fns.length) {
  16. fns.forEach((fn) => fn.apply(_this, arguments));
  17. }
  18. return _this;
  19. },
  20. off(event, fn) {
  21. // 取消订阅
  22. let _this = this;
  23. let fns = _this.list[event];
  24. if (!fns) return false;
  25. if (!fn) {
  26. fns.length = 0;
  27. } else {
  28. for (let i = 0; i < fns.length; i++) {
  29. if (fns[i] === fn || fns[i].fn === fn) {
  30. fns.splice(i, 1);
  31. break;
  32. }
  33. }
  34. }
  35. }
  36. };
  37. const user1 = (content) => {
  38. console.log("用户1订阅了:", content);
  39. };
  40. const user2 = (content) => {
  41. console.log("用户2订阅了:", content);
  42. };
  43. const user3 = (content) => {
  44. console.log("用户3订阅了:", content);
  45. };
  46. // 订阅
  47. eventEmitter.on("article1", user1);
  48. eventEmitter.on("article1", user2);
  49. eventEmitter.on("article2", user3);
  50. eventEmitter.emit("article1", "Javascript 发布-订阅模式");
  51. eventEmitter.emit("article2", "Javascript 观察者模式");
  52. eventEmitter.off("article1", user1);
  53. eventEmitter.emit("article1", "Javascript 发布-订阅模式");
  54. //用户1订阅了: Javascript 发布-订阅模式
  55. //用户2订阅了: Javascript 发布-订阅模式
  56. //用户3订阅了: Javascript 观察者模式
  57. //用户2订阅了: Javascript 发布-订阅模式

总结

学习设计模式不仅可以使我们用好这些成功的设计模式,更重要的是可以使我们深入理解面向对象的设计思想。

~

~本文完,感谢阅读!

~

学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!

大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!

你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!

知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

更多相关文章

  1. 快递100显示查询错误?快递100快递查询类FAQ
  2. 绝密公式算单双准确率99最强计划方案
  3. 17.)PHPWeb开发框架~Laravel中模型操作使用快速入门(AR模式)讲解
  4. TP6之多数据库,路由设置与多应用模式
  5. 0517 mvc架构模式思想
  6. 快递公司如何接入快递100?快递100的快递查询订阅推送接口示例
  7. 【MVC设计模式】PHP文件上传实战案例和MVC设计模式的原理和实现
  8. 漫画设计模式:什么是 “职责链模式” ?
  9. 漫画设计模式:什么是 “装饰器模式” ?

随机推荐

  1. 面试官:为什么静态方法不能调用非静态方法
  2. Android(安卓)自动化测试—robotium(一)环
  3. android中下载文件到SD卡的方法
  4. linux搭建SVN服务器
  5. android中fitsSystemWindows的用处
  6. Android(安卓)sdk 安装及Adk安装
  7. [Android(安卓)硬件] android手机主流屏
  8. 每日学习-ansible yum模块
  9. Android(安卓)关于手指拖动onScroll、onF
  10. Android(安卓)Bluetooth Address