谈谈javascript中设计模式第一篇

来源:互联网 发布:淘宝网商城购物 编辑:程序博客网 时间:2024/06/05 10:35

最近看了一本《Javascript设计模式与开发实践》;这本书写的很不错,书中举的例子也很通俗易懂。一早就想抽点时间写写的从中的感悟,好像也拖了好久了,什么课程设计呀,考试啦。今天终于静下来了。

首先我们来谈谈满大街都是的-单例模式:
单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式虽然简单,但是在javascript这种弱类型的语言中却又着举足轻重的地位;它可以减少命名空间污染。尤其在大型的项目。十分重要。

var A={};//如果对象a是独一无二的,我们就定义了一个单例对象A.sum=function(a,b){    return a+b;}A.multiply=function(a,b){    return a*b;}......

惰性单例:惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点,这种技术在实
际开发中非常有用,有用的程度可能超出了我们的想象。

Single.getInstance=(function(){    var instance=null;    return function(name){        if(!instance){            instance=new Single(name);        }    }    return instance;})();//来一个具体的例子,生成一个遮幕,这是我们在开发中经常会遇到的。    var createDiv=(function(){    var div;    return function(){        div=document.createElement("div");        div.style.width="100%";        div.style.height="100%";        div.style.zIndex="999";        docment.body.appendChild(div);    }    return div;})();

通用的惰性单例:

var getSingle = function( fn ){    var result;    return function(){    return result || ( result = fn .apply(this, arguments ) );    }};

现在我们来说说策略模式:
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
现在有一个问题是:根据用户的等级,返回用户每个月可领取的代金券数量。

var getVoucher=function(level){    if(level=="H"){        return 5;    }    if(level=="M"){        return 3;    }    if(level=="L"){        return 1;    }}

可以发现,这段代码十分简单,但是存在着显而易见的缺点。

  1. getVoucher函数比较庞大,包含了很多if-else 语句,这些语句需要覆盖所有的逻辑分支
  2. getVoucher 函数缺乏弹性,如果增加了一种新等级HH,那我们必须深入getVoucher 函数的内部实现,这是违反开放-封闭原则的。
  3. 算法的复用性差,如果在程序的其他地方需要重用用户每个月可领取的代金券数量?我们的选择只有复制和粘贴。

使用策略模式重构代码

//策略类var levelH=function(){};levelH.prototype.count=function(){    return 5;}var levelM=function(){};levelM.prototype.count=function(){    return 3;}var levelL=function(){};levelL.prototype.count=function(){    return 1;}// var personLevel=function(){    this.level=null;//原始等级}personLevel.prototype.setLevel=function(level){    this.level=level;//设置等级}personLevel.prototype.setCount=function(count){//设置策略类    this.count=count;}personLevel.prototype.getCount=function(){//获取代金券数量    return this.count.count(this.level)}

JavaScript 版本的策略模式

var   level={    "H":function(){                return 5;        },    "M":function(){                return 5;        },    "L":function(){                return 1;        }}//var personCount=function(level){    return level[level]();}console.log(personCount('H'));//输出5;

1.策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
2.策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy 中,使得它们易于切换,易于理解,3.易于扩展。
4.策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。
5.在策略模式中利用组合和委托来让Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案。
当然,策略模式也有一些缺点,但这些缺点并不严重。
首先,使用策略模式会在程序中增加许多策略类或者策略对象。其次,要使用策略模式,必须了解所有的策略类。

最后我们来聊聊代理模式:
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
代理分为:保护代理,虚拟代理,远程代理,缓存代理等等。
保护代理用于控制不同权限的对象对目标对象的访问,但在JavaScript 并不容易实现保护代理,因为我们无法判断谁访问了某个对象。而虚拟代理是最常用的一种代理模式,下面我们主要说虚拟代理。

虚拟代理实现图片预加载:
在Web 开发中,图片预加载是一种常用的技术,如果直接给某个img 标签节点设置src 属性,
由于图片过大或者网络不佳,图片的位置往往有段时间会是一片空白。常见的做法是先用一张
loading 图片占位,然后用异步的方式加载图片,等图片加载好了再把它填充到img 节点里,这种
场景就很适合使用虚拟代理。

var myImage = (function(){    var imgNode = document.createElement( 'img' );    document.body.appendChild( imgNode );    return {        setSrc: function( src ){            imgNode.src = src;        }  }})();myImage.setSrc( 'http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );

我们把网速调至5KB/s,然后通过MyImage.setSrc 给该img 节点设置src,可以看到,在图片被加载好之前,页面中有一段长长的空白时间。现在开始引入代理对象proxyImage,通过这个代理对象,在图片被真正加载好之前,页面中将出现一张占位的菊花图loading.gif, 来提示用户图片正在加载。代码如下:

var myImage = (function(){    var imgNode = document.createElement( 'img' );    document.body.appendChild( imgNode );    return {        setSrc: function( src ){        imgNode.src = src;        }    }    })();var proxyImage = (function(){    var img = new Image;    img.onload = function(){         myImage.setSrc( this.src );    }    return {            setSrc: function( src ){            myImage.setSrc( 'file:// /C:/Users/svenzeng/Desktop/loading.gif' );            img.src = src;        }    }})();

缓存代理用于ajax异步请求数据
我们在常常在项目中遇到分页的需求,同一页的数据理论上只需要去后台拉取一次,这些已经拉取到的数据在某个地方被缓存之后,下次再请求同一页的时候,便可以直接使用之前的数据。
这里写图片描述
一个网页中有4个tab标签,每切换一个就从后台抓取相对性的数据显示到content中。用缓存代理的话,每个tab只需要从后台抓取一次数据,减少请求。

//缓存代理去保存数据var proxyAjaxData=(function(){    var cache={};    return function(obj){//传入参数        if(obj in cache){            return cache[obj];//保存在cache中    }        return cache[obj]=getData();//从后台抓取的数据    }})();

本文章参考:《Javascript设计模式与开发实践》—–AlloyTeam出品

0 0
原创粉丝点击