刘志龙

2017-02-05 21:10

设计模式初探-代理模式

本文作者:IMWeb 刘志龙 原文出处:IMWeb社区 未经同意,禁止转载

是什么

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

生活是一切东西的起源,在生活中也到处能看到代理模式的影子。 明星有经纪人作为代理,要联系明星的档期其实是和经纪人联系,经纪人联系好之后,再有明星负责签约、演出。

想想平时工作中也有这种例子,每个小组都要发周报,组长负责周报的收集, 总监通过周报查看每个成员的工作情况,而不是每个成员都直接向总监汇报。

甚至古代也能找到类似的例子,挟天子以令诸侯,曹操和汉献帝的关系,也有代理模式的影子。

为什么

大概对代理模式有个模糊的概念了,那为什么要存在代理模式?

单一职责原则

想一想,明星为什么要有经纪人。经纪人可以负责帮助明星安排各种工作,对明星包装炒作等等。而明星自己只专注于演出。如果所有工作都交给明星自己完成,一个再高效再厉害的人估计也得忙疯了。

相应的,在面向对象设计原则中有单一职责原则,它规定一个类应该只有一个发生变化的原因。如果一个类承担了太多职责,这个类就会变得越来越庞大,难以维护。

对象无法被直接操作

还是看下明星和经纪人这个例子。作为一个大牌明星,不可能把自己的联系方式公开给大家。那别人怎么联系明星呢?经纪人这时候就起作用了,通过联系经纪人相当于间接的和明星有了联系。

对应程序设计里的场景,比如文档里面装了很大一张图片,在文档被打开的时候要加载里面的内容一起打开,但是如果等加载完这个大图片再打开文档用户要等太久,所以我们可以为这个图片设置一个代理,让代理慢慢打开这个图片而不影响文档本来的功能。

实际场景

权限管理

var User = {
    post: function () {
        console.log('发文章');
    },
    remove: function () {
        console.log('删除文章');
    }
}

var ProxyUser = {
    post: function () {
        if (有权限) {
            User.post();
        }

        console.log('没有权限发文章');
    },
    remove: funtion () {
        if (有权限) {
            User.remove();
        }

        console.log('没有权限删除文章');
    }
}

上面是一个简单的权限管理的例子。将权限管理的部分抽象出一个代理来实现。有人可能会说,代码本来可以写下面这么简单:

var User = {
    post: function () {
        if (有权限) {
            console.log('发文章');
        }

        console.log('没有权限发文章');
    },
    remove: funtion () {
        if (有权限) {
            console.log('删除文章');
        }

        console.log('没有权限删除文章');
    }
}

还非要搞个代理瞎折腾?

想想我们平时工作中越来越庞大的文件,想想每次改动一个小问题要折腾着把一个文件上千行代码看一遍,再想想前面提到的单一职责原则。我们发现这样分解其实是更易于维护的。用户类本身并不关注权限。

想想假设以后有个场景,不再需要权限控制了,使用了代理模式的场景,我们要做的只是把ProxyUser删了,接口换成User就完了。没有使用代理模式的,则是费尽心思改动这个User类。

再想想,之后我们权限规则有变动,只需要调整Proxy就好了,而并不关注用户到底是如何发文章,如何删除文章的。这也正是遵循了单一职责原则带来的好处。

loading态

我们经常遇到这样的场景,发一个ajax请求获得一堆数据,请求过程中展示loading态,数据回来隐藏loading,用请求回来的数据初始化模块。

这也可以用代理模式。

    var Mod = {
        init: function (data) {
            // 主逻辑
        }
    }

    var ProxyLoading = {
        init: function (mod) {
            showLoading();

            if (请求成功) {
                hideLoading();
                mod.init(data);
            } else {
                hideLoading();
            }
        } 
   }

   ProxyLoading.init(Mod);

简单的抽出一个Proxy来处理loading做的事情。

小结

代理模式远非这么简单,本文也只是作者此时此刻的理解,希望可以起到抛砖引玉的作用,不对之处还望各位大侠指正~~

0条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。