模式(一)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内部就使用了这种模式来处理事件捕获和冒泡的问题。


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


发送者知道链中第一个接收者,它向这个接收者发出请求。


每一个接收者都对请求进行分析,然后要么处理它,要么将其往下传。


每一个接收者知道的其他对象只有一个,即它在链中的下家。


如果没有任何接收者处理请求,那么请求将从链上离开,不同的实现对此也有不同的反应,一般会抛出一个错误。


小结:


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

相关文章
|
22天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
25天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
18天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
37 1
|
29天前
|
前端开发 JavaScript UED
探索JavaScript中的异步编程模式
【10月更文挑战第21天】在数字时代的浪潮中,JavaScript作为一门动态的、解释型的编程语言,以其卓越的灵活性和强大的功能在Web开发领域扮演着举足轻重的角色。本篇文章旨在深入探讨JavaScript中的异步编程模式,揭示其背后的原理和实践方法。通过分析回调函数、Promise对象以及async/await语法糖等关键技术点,我们将一同揭开JavaScript异步编程的神秘面纱,领略其带来的非阻塞I/O操作的魅力。让我们跟随代码的步伐,开启一场关于时间、性能与用户体验的奇妙之旅。
|
17天前
|
前端开发 JavaScript UED
探索JavaScript的异步编程模式
【10月更文挑战第33天】在JavaScript的世界里,异步编程是提升应用性能和用户体验的关键。本文将带你深入理解异步编程的核心概念,并展示如何在实际开发中运用这些知识来构建更流畅、响应更快的Web应用程序。从回调函数到Promises,再到async/await,我们将一步步解锁JavaScript异步编程的秘密,让你轻松应对各种复杂的异步场景。
|
1月前
|
设计模式 Java Kotlin
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin语法,推荐查看“简洁”系列教程。本文重点介绍了构建者模式在Kotlin中的应用与改良,包括如何使用具名可选参数简化复杂对象的创建过程,以及如何在初始化代码块中对参数进行约束和校验。
22 3
|
1月前
|
JavaScript 前端开发 API
探索Node.js中的异步编程模式
【10月更文挑战第4天】在JavaScript的世界中,异步编程是提升应用性能和用户体验的关键。本文将深入探讨Node.js中异步编程的几种模式,包括回调函数、Promises、async/await,并分享如何有效利用这些模式来构建高性能的后端服务。
|
1月前
|
JavaScript 前端开发 调度
探索Node.js中的异步编程模式
在Node.js的世界里,异步编程是核心。本文将带你深入了解异步编程的精髓,通过代码示例和实际案例分析,我们将一起掌握事件循环、回调函数、Promises以及async/await等关键概念。准备好迎接挑战,让你的Node.js应用飞起来!
|
1月前
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
33 3
|
1月前
|
JavaScript 前端开发 开发者
探索Node.js中的异步编程模式
【9月更文挑战第33天】在JavaScript的后端领域,Node.js凭借其非阻塞I/O和事件驱动的特性,成为高性能应用的首选平台。本文将深入浅出地探讨Node.js中异步编程的核心概念、Promise对象、Async/Await语法以及它们如何优化后端开发的效率和性能。
25 7
下一篇
无影云桌面