js代理模式

代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。

代理模式类图:

在上面类图中,代理模式所涉及的角色有三个:

抽象主题角色(Person):声明了真实主题和代理主题的公共接口,这样一来在使用真实主题的任何地方都可以使用代理主题。

代理主题角色(Friend):代 理主题角色内部含有对真实主题的引用,从而可以操作真实主题对象;代理主题角色负责在需要的时候创建真实主题对象;代理角色通常在将客户端调用传递到真实 主题之前或之后,都要执行一些其他的操作,而不是单纯地将调用传递给真实主题对象。例如这里的PreBuyProduct和PostBuyProduct 方法就是代理主题角色所执行的其他操作。

真实主题角色(RealBuyPerson):定义了代理角色所代表的真是对象。

附:在实际开发过程中,我们在客户端添加服务引用的时候,在客户程序中会添加一些额外的类,在客户端生成的类扮演着代理主题角色,我们客户端也是直接调用这些代理角色来访问远程服务提供的操作。这个是远程代理的一个典型例子。

先看一下C#的代理模式:

namespace 代理模式
{
    class Program
    {
        static void Main(string[] args)
        {
            SchoolGirl jiaojiao = new SchoolGirl();
            jiaojiao.Name = "李娇娇";

            Proxy daili = new Proxy(jiaojiao);

            daili.GiveDolls();
            daili.GiveFlowers();
            daili.GiveChocolate();


            Console.Read();
        }
    }

    //送礼物
    interface GiveGift
    {
        void GiveDolls();
        void GiveFlowers();
        void GiveChocolate();
    }

    class Proxy : GiveGift
    {
        Pursuit gg;
        public Proxy(SchoolGirl mm)
        {
            gg = new Pursuit(mm);
        }


        public void GiveDolls()
        {
            gg.GiveDolls();
        }

        public void GiveFlowers()
        {
            gg.GiveFlowers();
        }

        public void GiveChocolate()
        {
            gg.GiveChocolate();
        }
    }

    class Pursuit : GiveGift
    {
        SchoolGirl mm;
        public Pursuit(SchoolGirl mm)
        {
            this.mm = mm;
        }
        public void GiveDolls()
        {
            Console.WriteLine(mm.Name + " 送你洋娃娃");
        }

        public void GiveFlowers()
        {
            Console.WriteLine(mm.Name + " 送你鲜花");
        }

        public void GiveChocolate()
        {
            Console.WriteLine(mm.Name + " 送你巧克力");
        }
    }

    class SchoolGirl
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}

js模拟高级语言的代理模式:

var SchoolGirl = function(name){
        this.name = name;
    };
    
    var Pursuit = function(mm){
        this.mm = mm;
    };
    Pursuit.prototype.giveDolls = function(){
        alert(this.mm.name + '送你洋娃娃');
    };
    Pursuit.prototype.giveFlowers = function(){
        alert(this.mm.name + '送你鲜花');
    };
    Pursuit.prototype.giveChocolate = function(){
        alert(this.mm.name + '送你巧克力');
    };

    var Proxy = function(mm){
        this.gg = new Pursuit(mm);
    };
    Proxy.prototype.giveDolls = function(){
        this.gg.giveDolls();
    };
    Proxy.prototype.giveFlowers = function(){
        this.gg.giveFlowers();
    };
    Proxy.prototype.giveChocolate = function(){
        this.gg.giveChocolate();
    };


    //调用:
    var jiaojiao = new SchoolGirl();
    jiaojiao.name = "李娇娇";

    var daili = new Proxy(jiaojiao);

    daili.giveDolls();
    daili.giveFlowers();
    daili.giveChocolate();

js语言特性的代理模式:

var Flower = function(){};

    var Pursuit = {
        sendFlower:function(target){
            var flower = new Flower();
            target.receiveFlower(flower);
        }
    };

    var Proxy = {
        sendFlower:function(target){
            Pursuit.sendFlower(target);
        }
    };

    var SchoolGirl = {
        receiveFlower:function(flower){
            console.log('收到花' + flower);
        }
    };

    //调用:
    Proxy.sendFlower(SchoolGirl);

js虚拟代理实现图片预加载:

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;
            }
        }
    })();

    //调用:
    proxyImage.setSrc('http://imgcache.qq.com/music/photo/k/000GGDys0yAonk.jpg');

js缓存代理实现计算器:

//计算乘积
    var mult = function(){
        var a = 1;
        for(var i=0,l=arguments.length; i<l; i++){
            a = a * arguments[i];
        }
        return a;
    };

    //计算加和
    var plus = function(){
        var a = 0;
        for(var i=0,l=arguments.length; i<l; i++){
            a = a + arguments[i];
        }
        return a;
    };
    
    //创建缓存代理工厂
    var createProxyFactory = function(fn){
        var cache = {};
        return function(){
            var args = [].join.call(arguments,',');
            if(args in cache){
                return cache[args];
            }
            return cache[args] = fn.apply(this,arguments);
        }
    };


    //调用:
    var proxyMult = createProxyFactory(mult),
        proxyPlus = createProxyFactory(plus);

    alert(proxyMult(1,2,3,4)); //24
    alert(proxyMult(1,2,3,4)); //24
    alert(proxyPlus(1,2,3,4)); //10
    alert(proxyPlus(1,2,3,4)); //10

总结:代理模式包括许多小分类,在js开发中最常用的是虚拟代理和缓存代理。虽然代理模式非常有用,但我们在编写业务的时候,往往不需要去预先猜测是否需要使用代理模式。当真正发现不方便直接访问某个对象的时候,再编写代理也不迟。

原文地址:https://www.cnblogs.com/gongshunkai/p/6593886.html