美文网首页
javascript设计模式(代理模式)[转]

javascript设计模式(代理模式)[转]

作者: 尘中老 | 来源:发表于2016-09-14 21:48 被阅读0次

代理模式

代理是一个对象,它可以用来控制对本体对象的访问,它与本体对象实现了同样的接口,代理对象会把所有的调用方法传递给本体对象的;代理模式最基本的形式是对访问进行控制,而本体对象则负责执行所分派的那个对象的函数或者类,简单的来讲本地对象注重的去执行页面上的代码,代理则控制本地对象何时被实例化,何时被使用;我们在上面的单体模式中使用过一些代理模式,就是使用代理模式实现单体模式的实例化,其他的事情就交给本体对象去处理;
代理的优点:
代理对象可以代替本体被实例化,并使其可以被远程访问;
它还可以把本体实例化推迟到真正需要的时候;对于实例化比较费时的本体对象,或者因为尺寸比较大以至于不用时不适于保存在内存中的本体,我们可以推迟实例化该对象;

1、我们先来理解代理对象代替本体对象被实例化的列子;

比如现在京东ceo想送给奶茶妹一个礼物,但是呢假如该ceo不好意思送,或者由于工作忙没有时间送,那么这个时候他就想委托他的经纪人去做这件事,于是我们可以使用代理模式来编写如下代码:

// 先申明一个奶茶妹对象
var TeaAndMilkGirl = function(name) {
    this.name = name;
};
// 这是京东ceo先生
var Ceo = function(girl) {
    this.girl = girl;
    // 送结婚礼物 给奶茶妹
    this.sendMarriageRing = function(ring) {
        console.log("Hi " + this.girl.name + ", ceo送你一个礼物:" + ring);
    }
};
// 京东ceo的经纪人是代理,来代替送
var ProxyObj = function(girl){
    this.girl = girl;
    // 经纪人代理送礼物给奶茶妹
    this.sendGift = function(gift) {
        // 代理模式负责本体对象实例化
        (new Ceo(this.girl)).sendMarriageRing(gift);
    }
};
// 初始化
var proxy = new ProxyObj(new TeaAndMilkGirl("奶茶妹"));
proxy.sendGift("结婚戒"); // Hi 奶茶妹, ceo送你一个礼物:结婚戒

代码如上的基本结构,TeaAndMilkGirl是一个被送的对象(这里是奶茶妹);Ceo是送礼物的对象,他保存了奶茶妹这个属性,及有一个自己的特权方法sendMarriageRing就是送礼物给奶茶妹这么一个方法;然后呢他是想通过他的经纪人去把这件事完成,于是需要创建一个经济人的代理模式,名字叫ProxyObj;他的主要做的事情是,把ceo交给他的礼物送给ceo的情人,因此该对象同样需要保存ceo情人的对象作为自己的属性,同时也需要一个特权方法sendGift,该方法是送礼物,因此在该方法内可以实例化本体对象,这里的本体对象是ceo送花这件事情,因此需要实例化该本体对象后及调用本体对象的方法(sendMarriageRing).
最后我们初始化是需要代理对象ProxyObj;调用ProxyObj对象的送花这个方法(sendGift)即可;
对于我们提到的优点,第二点的话,我们下面可以来理解下虚拟代理,虚拟代理用于控制对那种创建开销很大的本体访问,它会把本体的实例化推迟到有方法被调用的时候;比如说现在有一个对象的实例化很慢的话,不能在网页加载的时候立即完成,我们可以为其创建一个虚拟代理,让他把该对象的实例推迟到需要的时候。
2、理解使用虚拟代理实现图片的预加载
在网页开发中,图片的预加载是一种比较常用的技术,如果直接给img标签节点设置src属性的话,如果图片比较大的话,或者网速相对比较慢的话,那么在图片未加载完之前,图片会有一段时间是空白的场景,这样对于用户体验来讲并不好,那么这个时候我们可以在图片未加载完之前我们可以使用一个loading加载图片来作为一个占位符,来提示用户该图片正在加载,等图片加载完后我们可以对该图片直接进行赋值即可;下面我们先不用代理模式来实现图片的预加载的情况下代码如下:
第一种方案:不使用代理的预加载图片函数如下

// 不使用代理的预加载图片函数如下
            var myImage = (function() {
                var imgNode = document.createElement("img");
                document.body.appendChild(imgNode);
                var img = new Image();
                img.onload = function() {
                    imgNode.src = this.src;
                };
                return {
                    setSrc: function(src) {
                        imgNode.src = "img/g.jpg"
                        img.src = src;
                    }
                }
            })();
            // 调用方式
            myImage.setSrc("http://img1.imgtn.bdimg.com/i=yxt.jpg");

如上代码是不使用代理模式来实现的代码;
第二种方案:使用代理模式来编写预加载图片的代码如下:

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("img/g.jpg");
                        img.src = src;
                    }
                }
            })();
            // 调用方式
            ProxyImage.setSrc("http://img1.imgtn.bdimg.com/i=yxt.jpg");

第一种方案是使用一般的编码方式实现图片的预加载技术,首先创建imgNode元素,然后调用myImage.setSrc该方法的时候,先给图片一个预加载图片,当图片加载完的时候,再给img元素赋值,第二种方案是使用代理模式来实现的,myImage函数只负责创建img元素,代理函数ProxyImage负责给图片设置loading图片,当图片真正加载完后的话,调用myImage中的myImage.setSrc方法设置图片的路径;
他们之间的 优缺点如下:

第一种方案一般的方法代码的耦合性太高,一个函数内负责做了几件事情,比如创建img元素,和实现给未加载图片完成之前设置loading加载状态等多项事情,未满足面向对象设计原则中单一职责原则;并且当某个时候不需要代理的时候,需要从myImage函数内把代码删掉,这样代码耦合性太高。

第二种方案使用代理模式,其中myImage函数只负责做一件事,创建img元素加入到页面中,其中的加载loading图片交给代理函数ProxyImage去做,当图片加载成功后,代理函数ProxyImage会通知及执行myImage函数的方法,同时当以后不需要代理对象的话,我们直接可以调用本体对象的方法即可;

从上面代理模式我们可以看到,代理模式和本体对象中有相同的方法setSrc,这样设置的话有如下2个优点:
用户可以放心地请求代理,他们只关心是否能得到想要的结果。假如我门不需要代理对象的话,直接可以换成本体对象调用该方法即可。

在任何使用本体对象的地方都可以替换成使用代理。
设计模式:http://www.cnblogs.com/tugenhua0707/p/5198407.html

相关文章

  • javascript设计模式(代理模式)[转]

    代理模式 代理是一个对象,它可以用来控制对本体对象的访问,它与本体对象实现了同样的接口,代理对象会把所有的调用方法...

  • JavaScript设计模式四(代理模式)

    JavaScript设计模式四(代理模式) 代理模式的定义: 代理模式是为一个对象提供一个代用品或者占位符,以便对...

  • Javascript设计模式-代理模式

    特点 1.使用者无法直接访问目标对象 2.使用者和目标对象之间加一层代理,通过代理来授权和控制 例如:访问gith...

  • JavaScript设计模式——代理模式

    代理模式 代理的概念 由于一个对象不能直接引用另一个对象,所以需要通过代理对象在这两个对象之间起到中介的作用 以上...

  • JavaScript设计模式——代理模式

    代理模式属于设计模式中结构型的设计模式; 定义:顾名思义就是为一个对象提供一个代用品或占位符,以便控制对它的访问!...

  • JavaScript设计模式——代理模式

    代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。 代理模式是一种非常有意义的模式,在生活中可以找到...

  • JavaScript设计模式--代理模式

    一、定义 代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。代理分为:保护代理和虚拟代理保护代理:用...

  • 设计模式系列笔记-代理模式

    写在前面:本系列文章内容为《JavaScript设计模式与开发实践》一书学习笔记,感谢作者曾探 代理模式 代理模式...

  • Javascript单例模式概念与实例

    前言 和其他编程语言一样,Javascript同样拥有着很多种设计模式,比如单例模式、代理模式、观察者模式等,熟练...

  • iOS 代理设计模式

    转自 <简书 — 刘小壮> 代理的基本使用 代理是一种通用的设计模式,在iOS中对代理设计模式支持的很好,有特定...

网友评论

      本文标题:javascript设计模式(代理模式)[转]

      本文链接:https://www.haomeiwen.com/subject/lfzvettx.html