资讯专栏INFORMATION COLUMN

JavaScript设计模式整理

zhangke3016 / 1098人阅读

摘要:写在前面设计模式是程序员通识知识,熟练掌握并使用各种设计模式,可以体现一个程序员的工程开发水平。我花了几天时间,重温并整理了多种设计模式,以为示例语言。节流模式对重复的业务逻辑进行节流控制,执行最后一次操作并取消其他操作,以提高性能。

写在前面

设计模式是程序员通识知识,熟练掌握并使用各种设计模式,可以体现一个程序员的工程开发水平。我花了几天时间,重温并整理了30多种设计模式,以JavaScript为示例语言。下面我会列出一些常用的设计模式说明及示例,更全面的内容见:https://github.com/yzsunlei/javascript-design-mode

什么是设计模式?

一个模式就是一个可重用的方案,可应用于在软件设计中的常见问题。另一种解释就是一个我们如何解决问题的模板 - 那些可以在许多不同的情况里使用的模板。

设计模式的分类:

创建型设计模式:
1、简单工厂模式
2、工厂方法模式
3、抽象工厂模式
4、建造者模式
5、原型模式
6、单例模式

结构型设计模式:
7、外观模式
8、适配器模式
9、代理模式
10、装饰者模式
11、桥接模式
12、组合模式
13、享元模式

行为型设计模式:
14、模板方法模式
15、观察者模式
16、状态模式
17、策略模式
18、职责链模式
19、命令模式
20、访问者模式
21、中介者模式
22、备忘录模式
23、迭代器模式
24、解释器模式

技巧型设计模式:
25、链模式
26、委托模式
27、数据访问对象模式
28、节流模式
29、简单模板模式
30、惰性模式
31、参与者模式
32、等待者模式

架构型设计模式:
33、同步模块模式
34、异步模块模式
35、Widget模式
36、MVC模式
37、MVP模式
38、MVVM模式

备注:该分类借鉴于《JavaScript设计模式-张容铭》

工厂方法模式:

通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例。

</>复制代码

  1. // 安全模式创建的工厂类
  2. var Factory = function(type, content) {
  3. if (this instanceof Factory) {
  4. // 保证是通过new进行创建的
  5. var s = new this[type](content);
  6. return s;
  7. } else {
  8. return new Factory(type, content);
  9. }
  10. };
  11. // 工厂原型中设置创建所有类型数据对象的基类
  12. Factory.prototype = {
  13. Java: function(content) {
  14. },
  15. Php: function(content) {
  16. },
  17. JavaScript: function(content) {
  18. }
  19. };
原型模式:

用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法。

</>复制代码

  1. // 图片轮播类
  2. var LoopImages = function(imgArr, container) {
  3. this.imagesArray = imgArr;
  4. this.container = container;
  5. };
  6. LoopImages.prototype = {
  7. // 创建轮播图片
  8. createImage: function() {
  9. console.log("LoopImages createImage function");
  10. },
  11. // 切换下一张图片
  12. changeImage: function() {
  13. console.log("LoopImages changeImage function");
  14. }
  15. };
  16. // 上下滑动切换类
  17. var SliderLoopImg = function(imgArr, container) {
  18. // 构造函数继承图片轮播类
  19. LoopImages.call(this, imgArr, container);
  20. };
  21. SliderLoopImg.prototype = new LoopImages();
  22. // 重写继承的“切换下一张图片”方法
  23. SliderLoopImg.prototype.changeImage = function() {
  24. console.log("SliderLoopImg changeImage function");
  25. };
单例模式:

又称单体模式,是只允许实例化一次的对象类。

</>复制代码

  1. // 惰性
  2. var LarySingle = (function() {
  3. // 单例实例引用
  4. var _instance = null;
  5. // 单例
  6. function Single() {
  7. // 这里定义私有属性和方法
  8. return {
  9. publicMethod: function() {},
  10. publicProperty: "1.0"
  11. };
  12. }
  13. // 获取单例对象接口
  14. return function() {
  15. // 如果未创建单例将创建单例
  16. if(!_instance){
  17. _instance = Single();
  18. }
  19. // 返回单例
  20. return _instance;
  21. };
  22. })();
外观模式:

为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。

</>复制代码

  1. function addEvent(dom, type, fn) {
  2. // 对于支持DOM2级事件处理程序addEventListener方法的浏览器
  3. if (dom.addEventListener) {
  4. dom.addEventListener(type, fn, false);
  5. } else if (dom.attachEvent) {
  6. // 对于不支持addEventListener方法但支持attchEvent方法的浏览器
  7. dom.attachEvent("on" + type, fn);
  8. } else {
  9. // 对于不支持addEventListener方法,也不支持attchEvent方法,但支持“on”+事件名的浏览器
  10. dom["on" + type] = fn;
  11. }
  12. }
装饰者模式:

在不改变原对象的基础上,通过对其进行包装拓展(添加属性或方法)使原对象可以满足用户更复杂需求。

</>复制代码

  1. var decorator = function (input, fn) {
  2. // 获取事件源
  3. var input = document.getElementById(input);
  4. // 若事件源已经绑定事件
  5. if (typeof input.click === "function") {
  6. // 缓存事件源原有回调函数
  7. var oldClickFn = input.click;
  8. // 为事件源定义新的事件
  9. input.click = function () {
  10. // 事件源原有回调函数
  11. oldClickFn();
  12. // 执行事件源新增回调函数
  13. fn();
  14. }
  15. } else {
  16. // 事件源未绑定事件,直接为事件源添加新增回调函数
  17. input.onclick = fn;
  18. }
  19. }
观察者模式:

又称发布-订阅者模式或消息机制,定义一种依赖关系,解决了主体对象与观察者之间功能的耦合。

</>复制代码

  1. var Observer = (function () {
  2. var __messages = {};
  3. return {
  4. // 注册消息
  5. register: function (type, fn) {
  6. if (typeof __messages[type] === "undefined") {
  7. __messages[type] = [fn];
  8. } else {
  9. __messages[type].push(fn);
  10. }
  11. },
  12. // 发布消息
  13. fire: function (type, args) {
  14. if (!__messages[type])
  15. return;
  16. var events = {
  17. type: type,
  18. args: args || {}
  19. };
  20. var i = 0;
  21. var len = __messages[type].length;
  22. for (; i < len; i++) {
  23. __messages[type][i].call(this, events);
  24. }
  25. },
  26. // 移除消息
  27. remove: function (type, fn) {
  28. if (__messages[type] instanceof Array) {
  29. var i = __messages[type].length - 1;
  30. for (; i >= 0; i--) {
  31. __messages[type][i] == fn && __messages[type].splice(i, 1);
  32. }
  33. }
  34. }
  35. }
  36. })();
状态模式:

当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。

</>复制代码

  1. // 状态对象
  2. var ResultState = function () {
  3. var States = {
  4. state0: function () {
  5. console.log("第一种情况");
  6. },
  7. state1: function () {
  8. console.log("第二种情况");
  9. },
  10. state2: function () {
  11. console.log("第三种情况");
  12. },
  13. state3: function () {
  14. console.log("第四种情况");
  15. }
  16. };
  17. function show(result) {
  18. States["state" + result] && States["state" + result]();
  19. }
  20. return {
  21. show: show
  22. }
  23. }();
命令模式:

将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数化。

</>复制代码

  1. // 绘图命令
  2. var CanvasCommand = (function () {
  3. var canvas = document.getElementById("canvas");
  4. var ctx = canvas.getContext("2d");
  5. var Action = {
  6. fillStyle: function (c) {
  7. ctx.fillStyle = c;
  8. },
  9. fillRect: function (x, y, w, h) {
  10. ctx.fillRect(x, y, w, h);
  11. },
  12. strokeStyle: function (c) {
  13. ctx.strokeStyle = c;
  14. },
  15. strokeRect: function (x, y, w, h) {
  16. ctx.strokeRect(x, y, w, h);
  17. },
  18. fillText: function (text, x, y) {
  19. ctx.fillText(text, x, y);
  20. },
  21. beginPath: function () {
  22. ctx.beginPath();
  23. },
  24. moveTo: function (x, y) {
  25. ctx.moveTo(x, y);
  26. },
  27. lineTo: function (x, y) {
  28. ctx.lineTo(x, y);
  29. },
  30. arc: function (x, y, r, begin, end, dir) {
  31. ctx.arc(x, y ,r, begin, end, dir);
  32. },
  33. fill: function () {
  34. ctx.fill();
  35. },
  36. stroke: function () {
  37. ctx.stroke();
  38. }
  39. };
  40. return {
  41. excute: function (msg) {
  42. if (!msg)
  43. return;
  44. if (msg.length) {
  45. for (var i = 0, len = msg.length; i < len; i++) {
  46. arguments.callee(msg[i]);
  47. }
  48. } else {
  49. msg.param = Object.prototype.toString.call(msg.param) === "[object Array]" ? msg.param : [msg.param];
  50. Action[msg.command].apply(Action, msg.param);
  51. }
  52. }
  53. }
  54. })();
迭代器模式:

在不暴露对象内部结构的同时,可以顺序的访问聚合对象内部的元素。

</>复制代码

  1. // 迭代器
  2. var Iterator = function (items, container) {
  3. var container = container && document.getElementById(container) || document;
  4. var items = container.getElementsByTagName(items);
  5. var len = items.length;
  6. var idx = 0;
  7. var splice = [].splice();
  8. return {
  9. first: function () {},
  10. second: function () {},
  11. pre: function () {},
  12. next: function () {},
  13. get: function () {},
  14. dealEach: function () {},
  15. dealItem: function () {},
  16. exclusive: function () {}
  17. }
  18. };
链模式:

通过在对象方法中将当前对象返回,实现对同一个对象多个方法的链式调用。

</>复制代码

  1. var A = function (selector) {
  2. return new A.fn.init(selector);
  3. };
  4. A.fn = A.prototype = {
  5. constructor: A,
  6. init: function (selector) {
  7. console.log(this.constructor);
  8. }
  9. };
  10. A.fn.init.prototype = A.fn;
节流模式:

对重复的业务逻辑进行节流控制,执行最后一次操作并取消其他操作,以提高性能。

</>复制代码

  1. var throttle = function () {
  2. var isClear = arguments[0];
  3. var fn;
  4. if (typeof isClear === "boolean") {
  5. fn = arguments[1];
  6. fn.__throttleID && clearTimeout(fn.__throttleID);
  7. } else {
  8. fn = isClear;
  9. param = arguments[1];
  10. var p = extend({
  11. context: null,
  12. args: [],
  13. time: 30
  14. }, param);
  15. arguments.callee(true, fn);
  16. fn.__throttleID = setTimeout(function () {
  17. fn.apply(p.context, p.args);
  18. }, p.time);
  19. }
  20. }
参与者模式:

在特定的作用域中执行给定的函数,并将参数原封不动的传递。

</>复制代码

  1. // 函数绑定
  2. function bind(fn, context) {
  3. return function () {
  4. return fn.apply(context, arguments);
  5. }
  6. }
  7. // 函数柯里化
  8. function curry(fn) {
  9. var Slice = [].slice;
  10. var args = Slice.call(arguments, l);
  11. return function () {
  12. var addArgs = Slice.call(arguments);
  13. var allArgs = args.concat(addArgs);
  14. return fn.apply(null, allArgs);
  15. }
  16. }
参考资料

https://book.douban.com/subject/26589719/

https://book.douban.com/subject/26382780/

https://www.w3cschool.cn/zobyhd/m1w6jozt.html

https://www.cnblogs.com/xiyangbaixue/p/3902699.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104873.html

相关文章

  • 前端学习资源整理

    稍微整理了一下自己平时看到的前端学习资源,分享给大家。 html MDN:Mozilla开发者网络 SEO:前端开发中的SEO css 张鑫旭:张鑫旭的博客 css精灵图:css精灵图实践 栅格系统:详解CSS中的栅格系统 媒体查询:css媒体查询用法 rem布局:手机端页面自适应布局 移动前端开发之viewport的深入理解:深入理解viewport 淘宝前端布局:手机淘宝移动端布局 fl...

    siberiawolf 评论0 收藏0
  • JavaScript 中常见设计模式整理

    摘要:开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 showImg(https://segmentfault.com/img/remote/1460000014919705?w=640&h=280); 开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设...

    Nosee 评论0 收藏0
  • Javascript设计模式资源整理

    Javascript设计模式详解

    freewolf 评论0 收藏0
  • 前端进阶资源整理

    摘要:前端进阶进阶构建项目一配置最佳实践状态管理之痛点分析与改良开发中所谓状态浅析从时间旅行的乌托邦,看状态管理的设计误区使用更好地处理数据爱彼迎房源详情页中的性能优化从零开始,在中构建时间旅行式调试用轻松管理复杂状态如何把业务逻辑这个故事讲好和 前端进阶 webpack webpack进阶构建项目(一) Webpack 4 配置最佳实践 react Redux状态管理之痛点、分析与...

    BlackMass 评论0 收藏0
  • W3School 教程整理

    摘要:离线版大部分整理自,少部分整理自,由本人整理。感谢站长的无私奉献。由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 离线版大部分整理自 w3cschool ,少部分整理自 w3school ,由本人整理。 感谢 w3cschool 站长的无私奉献。 由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 AngularJS教程 最后更...

    douzifly 评论0 收藏0
  • W3School 教程整理

    摘要:离线版大部分整理自,少部分整理自,由本人整理。感谢站长的无私奉献。由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 离线版大部分整理自 w3cschool ,少部分整理自 w3school ,由本人整理。 感谢 w3cschool 站长的无私奉献。 由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 AngularJS教程 最后更...

    CoffeX 评论0 收藏0

发表评论

0条评论

zhangke3016

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<