谈谈javascript中设计模式第一篇 - Go语言中文社区

谈谈javascript中设计模式第一篇


最近看了一本《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出品

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/baidu_24024601/article/details/51559239
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-31 13:03:58
  • 阅读 ( 1277 )
  • 分类:设计模式

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢