模式(一)javascript设计模式

模式有三种:Architectural Pattern、Design Pattern、Coding Pattern,即:框架模式、设计模式、编程模式。本文主要讲解javascript中的设计模式,好的设计模式能够提高代码的重用性,可读性,使代码更容易的维护和扩展。本文适合有一点javascript基础,对javascript的概念有所了解。

一、单例模式:

 单例模式是javascript中最常用的模式,它是将自己的代码放在一个命名空间下,这样的好处是可以减少使用全局变量,在多人协同开发时也能避免命名冲突等问题。这样的好处是维护起来非常方便,如下例:

1 var m = {
2     name: 'dog',
3     action: function() {
4         console.log(this.name);
5     }
6 };
7 m.action();//调用

 

或者

1 var dog = function() {
2     this.name = 'dog';
3     this.action = function() {
4         return console.log(this.name);
5     };
6     action();
7 };
8 dog(); //调用

 

工厂模式:

工厂模式就是将对象的方法创建交给外部对象,这样的好处就是解决了对象之间的相互影响、即耦合,避免了使用new来实例化对象,有助于创建模块化的代码,维护起来也方便。 工厂模式分为简单工厂模式和抽象工厂模式,下面介绍简单工厂模式:

1 var m = {};
2 m.action = function() {
3     console.log('dog');
4 };
5 var demo = function() {
6     m.action();
7 };
8 demo()//调用

 

抽象工厂模式先设计一个抽象类,这个类不能被实例化,只能用来派生子类,最后通过对子类的扩展实现工厂方法。如下:

 1 var f = function() {};
 2 f.prototype = {
 3     c: function() {
 4         throw new Error('can\'t use this method');//如果调用此方法会报错,因为它是用来派生子类不能实例化
 5     }
 6 };
 7 var e = function() {
 8     f.call(this);
 9 }
10 e.prototype = new f();
11 e.prototype.constructor = e;
12 e.prototype.c = function() {
13     console.log('this method is redefine');
14 }
15 // 调用
16 var demo = new e();
17 demo.c();

 

桥接模式:

桥接模式是将抽象与实现隔离,一遍二者独立变化。在设计一个javascript API的时候,它可以用来弱化类和对象之间的耦合。它还可以用来把多个类联接在一起。例如:

 1 var class1 = function(a,b,c) {
 2     this.a = a;
 3     this.b = b;
 4     this.c = c;
 5 };
 6 var class2 = function(d) {
 7     this.d = d;
 8 };
 9 var demo = function(a,b,c,d) {
10     this.one = new Class1(a,b,c);
11     this.two = new Class2(d);
12 };

 

组合模式:

组合模式可以用一条命令在多个对象上激发复杂的或递归的行为。好处是可以用同样的发放处理对象的集合与其中的特定子对象,也可以用来把一批子对象组织成树形结构,并且使整个树都可被遍历。如下:

 1 // DynamicGallery Class
 2   var DynamicGallery =function (id) { // 实现Composite,GalleryItem组合对象类 
 3      this.children = [];
 4      this.element = document.createElement('div');
 5      this.element.id = id;
 6      this.element.className ='dynamic-gallery';
 7   }
 8   DynamicGallery.prototype = {
 9      // 实现Composite组合对象接口 
10      add: function (child) {
11         this.children.push(child);
12         this.element.appendChild(child.getElement());
13      },
14      remove: function (child) {
15         for (var node, i =0; node =this.getChild(i); i++) {
16            if (node == child) {
17               this.children.splice(i, 1);
18               break;
19            }
20         }
21         this.element.removeChild(child.getElement());
22      },
23      getChild: function (i) {
24         returnthis.children[i];
25      },
26      // 实现DynamicGallery组合对象接口 
27      hide: function () {
28         for (var node, i =0; node =this.getChild(i); i++) {
29            node.hide();
30         }
31         this.element.style.display ='none';
32      },
33      show: function () {
34         this.element.style.display ='block';
35         for (var node, i =0; node = getChild(i); i++) {
36            node.show();
37         }
38      },
39      // 帮助方法 
40      getElement: function () {
41         returnthis.element;
42      }
43   }

 

 1 var GalleryImage =function (src) { // 实现Composite和GalleryItem组合对象中所定义的方法 
 2      this.element = document.createElement('img');
 3      this.element.className ='gallery-image';
 4      this.element.src = src;
 5   }
 6   GalleryImage.prototype = {
 7      // 实现Composite接口 
 8      // 这些是叶结点,所以我们不用实现这些方法,我们只需要定义即可 
 9      add: function () { },
10      remove: function () { },
11      getChild: function () { },
12      // 实现GalleryItem接口 
13      hide: function () {
14         this.element.style.display ='none';
15      },
16      show: function () {
17         this.element.style.display ='';
18      },
19      // 帮助方法 
20      getElement: function () {
21         returnthis.element;
22      }
23   }
 1 var topGallery =new DynamicGallery('top-gallery'); 
 2   topGallery.add(new GalleryImage('/img/image-1.jpg')); 
 3   topGallery.add(new GalleryImage('/img/image-2.jpg')); 
 4   topGallery.add(new GalleryImage('/img/image-3.jpg')); 
 5   var vacationPhotos =new DyamicGallery('vacation-photos'); 
 6   for(var i =0, i <30; i++){ 
 7     vacationPhotos.add(new GalleryImage('/img/vac/image-'+ i +'.jpg')); 
 8   } 
 9   topGallery.add(vacationPhotos); 
10   topGallery.show(); 
11   vacationPhotos.hide();

 

门面模式:

门面模式常常是开发人员最亲密的朋友,他几乎是所有javascript库的核心原则。门面模式有两个作用:一是简化类的接口;二是消除类与使用它的客户代码之间的耦合。示例如下:

 1 function a() {
 2 
 3 }
 4 function b() {
 5 
 6 }
 7 function ab() {
 8     a();
 9     b();
10 }

 

适配器模式:

适配器模式可以用来在现有接口和不兼容的类之间进行适配。从表面上看,适配器模式很像门面模式,都对别的对象进行包装并改变其呈现的接口。二者的区别在与它们如何改变接口,门面元素展现的是一个简化的接口,它并不提供额外的选择,而且有时为了方便完成常见任务它还会做出一些假定。而适配器则要把一个接口转换为另一个接口,它并不会过滤某些能力,也不会简化接口。

 1 var str = {
 2     a: 'a',
 3     b: 'b',
 4     c: 'c'
 5 };
 6 function i(s1,s2,s3) {
 7     console.log(s1 + ',' + s2 + ',' + s3);
 8 }
 9 function demo(o) {
10     i(o.a,o.b,o.c);
11 }

 

装饰者模式:

装饰者模式可用来透明地把对象包装在具有同样接口的另一个对象之中,装饰者可以用于为对象添加功能,可以用来代替大量子类。装饰者模式和组合模式有很多共同点,它们都与所包装的对象实现统一的接口并且会把任何方法条用传递给这些对象。可是组合模式用于把众多子对象组织为一个整体,而装饰者模式用于在不修改现有对象或从派生子类的前提下为其添加方法。如下:

1 var m = {};
2 m.child = {};
3 m.child.one = function() {};
4 m.child.two = function() {};

 

 享元模式:

 享元模式最适合于解决因创建大量类似对象而累及性能的问题。通过把大量独立对象转化为少量共享对象,可以降低运行web应用程序所需的资源数量。

javascript设计模式中的示例:

 1 //汽车登记示例
 2   var Car =function(make,model,year,owner,tag,renewDate){
 3     this.make=make;
 4     this.model=model;
 5     this.year=year;
 6     this.owner=owner;
 7     this.tag=tag;
 8     this.renewDate=renewDate;
 9   }
10   Car.prototype = {
11     getMake:function(){
12       returnthis.make;
13     },
14     getModel:function(){
15       returnthis.model;
16     },
17     getYear:function(){
18       returnthis.year;
19     },
20     transferOwner:function(owner,tag,renewDate){
21       this.owner=owner;
22       this.tag=tag;
23       this.renewDate=renewDate;
24     },
25     renewRegistration:function(renewDate){
26       this.renewDate=renewDate;
27     }
28   }
29   //数据量小到没多大的影响,数据量大的时候对计算机内存会产生压力,下面介绍享元模式优化后
30   //包含核心数据的Car类
31   var Car=function(make,model,year){
32     this.make=make;
33     this.model=model;
34     this.year=year;
35   }
36   Car.prototype={
37     getMake:function(){
38       returnthis.make;
39     },
40     getModel:function(){
41       returnthis.model;
42     },
43     getYear:function(){
44       returnthis.year;
45     }
46   }
47   //中间对象,用来实例化Car类
48   var CarFactory=(function(){
49     var createdCars = {};
50     return {
51       createCar:function(make,model,year){
52         var car=createdCars[make+"-"+model+"-"+year];
53         return car ? car : createdCars[make +'-'+ model +'-'+ year] =(new Car(make,model,year));
54       }
55     }
56   })();
57   //数据工厂,用来处理Car的实例化和整合附加数据
58   var CarRecordManager = (function() {
59     var carRecordDatabase = {};
60     return {
61       addCarRecord:function(make,model,year,owner,tag,renewDate){
62         var car = CarFactory.createCar(make, model, year);
63         carRecordDatabase[tag]={
64           owner:owner,
65           tag:tag,
66           renewDate:renewDate,
67           car:car
68       }
69     },
70       transferOwnership:function(tag, newOwner, newTag, newRenewDate){
71         var record=carRecordDatabase[tag];
72         record.owner = newOwner;
73         record.tag = newTag;
74         record.renewDate = newRenewDate;
75       },
76       renewRegistration:function(tag,newRenewDate){
77         carRecordDatabase[tag].renewDate=newRenewDate;
78       },
79       getCarInfo:function(tag){
80         return carRecordDatabase[tag];
81       }
82     }
83   })();

 

代理模式:

代理是一个对象,它可以用来控制对另一个对象的访问。它与另外那个对象实现了同样的接口,并且会把任何方法调用传递给那个对象。代理模式适合处理实例化比较费时的本体,也适合处理那些需要较长时间才能把数据载入用户界面的类。

javascript设计模式中的示例:

 1 var Publication =new Interface('Publication', ['getIsbn', 'setIsbn', 'getTitle', 'setTitle', 'getAuthor', 'setAuthor', 'display']);
 2   var Book =function(isbn, title, author) {
 3       //...
 4   } 
 5   // implements Publication
 6   implements(Book,Publication);
 7 
 8   /* Library interface. */
 9   var Library =new Interface('Library', ['findBooks', 'checkoutBook', 'returnBook']);
10 
11   /* PublicLibrary class. */
12   var PublicLibrary =function(books) {
13       //...
14   };
15   // implements Library
16   implements(PublicLibrary,Library); 
17 
18   PublicLibrary.prototype = {
19       findBooks: function(searchString) {
20          //...
21       },
22       checkoutBook: function(book) {
23           //...
24       },
25       returnBook: function(book) {
26           //...
27       }
28   };
29 
30   /* PublicLibraryProxy class, a useless proxy. */
31   var PublicLibraryProxy =function(catalog) { 
32       this.library =new PublicLibrary(catalog);
33   };
34   // implements Library
35   implements(PublicLibraryProxy,Library);
36 
37   PublicLibraryProxy.prototype = {
38       findBooks: function(searchString) {
39           returnthis.library.findBooks(searchString);
40       },
41       checkoutBook: function(book) {
42           returnthis.library.checkoutBook(book);
43       },
44       returnBook: function(book) {
45           returnthis.library.returnBook(book);
46       }
47   };

 

观察者模式:

观察者模式是一种管理人与其任务之间的关系的得力工具。观察者模式中存在两个角色:观察者和被观察者。这种模式的好处是你可以对程序中某个对象的状态进行观察,并且在其发生改变时能够得到通知。

 1   var f1 =function(){
 2      //code
 3   }
 4   var f2 =function(){
 5      //code
 6   }
 7   addEvent(element,'click',f1);
 8   addEvent(element,'click',f2)
 9 
10 
11   element.onclick = f1;
12   element.onclick = f2;

 

命令模式:

命令模式可以用来对方法调用进行参数化处理和传送,经这样处理过的方法调用可以在任何需要的时候执行。好处是可以用来消除调用操作的对象和实现操作的对象之间的耦合,使对象间的互动方式更高的模块化。这为各种具体的类更换带来了极大的灵活性。

 1 car Calculator={
 2      add:function(x,y){
 3         return x+y;
 4      },
 5      substract:function(x,y){
 6         return x-y;
 7      },
 8      multiply:function(x,y){
 9         return x*y;
10      },
11      divide:function(x,y){
12         return x/y;
13      }
14   }
15   Calculator.calc =function(command){
16      return Calculator[command.type](command.op1,command.opd2)
17   };
18   Calculator.calc({type:'add',op1:1,op2:1});
19   Calculator.calc({type:'substract',op1:5,op2:2});
20   Calculator.calc({type:'multiply',op1:5,op2:2});
21   Calculator.calc({type:'divide',op1:8,op2:4});

 

职责链模式:

职责链模式是通过实现一个由隐式地请求进行处理对象组成的链而做到的。可以用来消除请求的发送者和接收者之间的耦合

javascript内部就使用了这种模式来处理事件捕获和冒泡的问题。

职责链由多个不同类型的对象组成:发送者是发出请求的对象,而接收者则是接收请求并且对其进行处理或传递的对象,请求本身有时也是一个对象,它封装着与操作有关的所有数据。其典型的流程大致是:

  1. 发送者知道链中第一个接收者,它向这个接收者发出请求。
  2. 每一个接收者都对请求进行分析,然后要么处理它,要么将其往下传。
  3. 每一个接收者知道的其他对象只有一个,即它在链中的下家。
  4. 如果没有任何接收者处理请求,那么请求将从链上离开,不同的实现对此也有不同的反应,一般会抛出一个错误。

小结:

  每种模式都有自己的优点,选择一种适合自己业务的模式非常重要,能够提高代码的可读性、可维护性等等,希望本文能够对你有所帮助。

 

本文参考电子书《javascript设计模式》

 

转载于:https://www.cnblogs.com/xiyangbaixue/p/3902699.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab如何提高运算速速,如何提高以下程序的运算速度及有选择性的保存数据?...

多谢管理员math的关注。“空位随机游走过程”有英语我也不知道如何说。只知道“空位”叫做&#xff1a;vacancy我解解释一下整个过程。不过过程比较长一些&#xff01;为了说明问题&#xff0c;我就举个例子如&#xff1a;Fe-Mg二元合金&#xff0c;其中Mg占3%&#xff0c;空位…

GPS经纬度换算成XY坐标

/// <summary>///GPS经纬度换算成x,y坐标 /// </summary>/// <param name"l"> 精度 </param>/// <param name"B"> 纬度 </param>/// <param name"xc"> X坐标 </param>/// <param na…

Valid Sudoku

这道题是个细节实现题&#xff0c;只要把valid sudoku满足的三个条件判断一下即可。 valid sudoku需满足下列三个条件&#xff1a; 1&#xff09;每一行数字1~9有且只出现一次。2&#xff09;每一列数字1~9有且只出现一次。3&#xff09;对于每个3*3的sub-box&#xff08;用i3、…

CosiWorksNew

CMainFrameCBCGPRibbonBar m_wndRibbonBar; 工具栏CreateRibbonBar() 构建工具栏CWProjectBar m_wndProjectBar; 左侧的工程窗口CWModelLibBar m_wndModellibBar; 左侧的模型窗口ShowControlBar(CBCGPDockingControlBar*, BOOL, BOOL, BOOL) 显示或隐藏左侧窗…

make xdb file.php,SCWS入门使用指南

B 结合php使用要想在php中使用scws分词工具&#xff0c;必须安装php扩展&#xff0c;并且必须要求php与scws安装在同一台机器。cd /usr/local/src/scws-1.2.2/usr/local/php-5.3.8/bin/phpize ./configure --with-scws/usr/local/scws --with-php-config/usr/local/php-5…

异步编程中的最佳做法(Async/Await) --转

近日来&#xff0c;涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支持的信息。 本文旨在作为学习异步编程的“第二步”&#xff1b;我假设您已阅读过有关这一方面的至少一篇介绍性文章。 本文不提供任何新内容&#xff0c;Stack Overflow、MSDN 论坛…

spline 用法

控制actor在level中沿着一个spline path运动。 由finterp to 函数的输出数值来控制每一帧actor运动的距离。 从开始位置到spline path的终点的时间&#xff0c;是1/interp speed。假如我们控制actor从开头到终点运动的总时间是1秒&#xff0c;那么 interp speed就传入0.5&#…

php 时间戳获取周几,PHP实现根据时间戳获取周几的方法,php戳获取周_PHP教程

PHP实现根据时间戳获取周几的方法&#xff0c;php戳获取周本文实例讲述了PHP实现根据时间戳获取周几的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;获取某个时间戳的周几&#xff0c;以及未来几天以后的周几其中&#xff1a;$time 代表时间$i 今天开始具体示例…

HTML5 Canvas 高仿逼真 3D 布料图案效果

HTML5 规范引进了很多新特性&#xff0c;其中最令人期待的之一就是 Canvas 元素&#xff0c;HTML5 Canvas 提供了通过 JavaScript 绘制图形的方法&#xff0c;非常强大。下面给大家分享一个 HTML5 Canvas 绘制的 3D 布料图案效果。 温馨提示&#xff1a;为保证最佳的效果&#…

oracle中exp/imp讲解

Exp/Imp是oracle备份数据的两个命令行工具 1.本地数据库导入导出 1.导出 &#xff08;运行---cmd中操作&#xff09; exp 用户名/密码数据库实例名file本地存放路径 eg: exp jnjp/jnjpORCL fileC:/jnjp.dmp2.导入 imp 用户名/密码数据库实例名file本地数据库文件存放路径fully …

用toad实现oracle数据迁移,Oracle 使用TOAD实现导入导出Excel数据

在Oracle应用程序的开发过程中&#xff0c;访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作&#xff0c;对数据库进行日常管理也是需要很多SQL脚本才能完成的。Quest Software为此提供了高效的Oracle应用开发工具-Toad。在Toad的新版本中&#xff0c;还加入了DBA模块&a…

本地windows主机无法访问虚拟机里主机解决办法

一&#xff1a;设置虚拟机里IP&#xff0c;使其与本地计算机IP在同一网段 本地计算机网络IP设置如下&#xff1a; 虚拟机里ip为192.168.1.9 设置IP步骤请参考&#xff1a;Linux里如何设置IP(RED HAT) 二&#xff1a;将虚拟机网络连接方式设为桥接 假如&#xff0c;VirtualBox不…

Oracle创建用户、角色、授权、建表

oracle数据库的权限系统分为系统权限与对象权限。系统权限( database system privilege )可以让用户执行特定的命令集。例如&#xff0c;create table权限允许用户创建表&#xff0c;grant any privilege 权限允许用户授予任何系统权限。对象权限( database object privilege )…

linux服务器3306端口,linux系统对外开放3306、8080等端口,防火墙设置详解

linux系统对外开放3306、8080等端口&#xff0c;防火墙设置详解发布时间&#xff1a;2020-10-10 23:08:49来源&#xff1a;脚本之家阅读&#xff1a;141作者&#xff1a;julielele栏目&#xff1a;服务器我们很多时候在liunx系统上安装了web服务应用后(如tomcat、apache等)&…

hdu--1231--并查集连分量的个数

我觉得 这题 是纯粹的 并查集 可以算成 入门题吧 问你有几章桌子 就是问你有几个 连通块嘛 一个道理 touch me 这题 我采用了下 father[x]开始 初始化为-1 1 #include <iostream>2 #include <cstring>3 using namespace std;4 5 const int size 1010;6 int fathe…

linux查询服务器的dns,如何查看Linux系统中DNS服务器的运行状况

DNS是分布式数据库&#xff0c;可以让用户们方便访问互联网&#xff0c;而主机的dns服务器也直接影响了我们上网及访问网站的速度&#xff0c;那么你知道如何查看Linux系统中DNS服务器的运行状况吗&#xff1f;在Linux环境下&#xff0c;也提供了广泛流行的BIND服务器&#xff…

landscape 1

1. 创建出landscape的分层材质2. 把材质添加给landscape后&#xff0c;可以在landscape的画刷模式下看到3. 通过点击右侧的加号&#xff0c;依次添加layer后&#xff0c;就可以使用他们进行地形的绘制。 通过右键菜单可以快速填充和清除对应的layer4. 用下面的方法修改材质的法…

linux进程和线程教程,Linux下查看进程和线程

在Linux中查看线程数的三种方法1、top -H手册中说&#xff1a;-H : Threads toggle加上这个选项启动top&#xff0c;top一行显示一个线程。否则&#xff0c;它一行显示一个进程。2、ps xH手册中说&#xff1a;H Show threads as if they were processes这样可以查看所有存在的线…

ORA-12154: TNS: 无法解析指定的连接标识符

相信使用过Oracle数据库的人一定碰到过“ORA-12154: TNS: 无法解析指定的连接标识符”错误&#xff0c;我在此做一个小小的总结。在程序中连接Oracle数据库的方式与其他常用数据库&#xff0c;如&#xff1a;MySql,Sql Server不同&#xff0c;这些数据库可以通过直接指定IP的方…

任务管理器启动资源管理器

今天远程桌面登录windows服务器竟然发现没有Windows Explorer&#xff08;资源管理器&#xff09;了&#xff01;桌面啥的都没有&#xff0c;只有几个孤零零的命令行窗口。。。 输入ctrlaltend启动远程桌面的任务管理器&#xff0c;选择File->run new task 输入explorer.exe…