【技巧篇】JavaScript设计模式之策略模式应用

148 阅读3分钟

看标题好像非常高大威猛的样子😂,且不要被题目吓到,或许这个技巧很多朋友在工作中都运用过,只是可能不够完善或者不care这种写法属于什么设计模式。

是的,我们的目的很明确,就是DRY——Don't repeat yourself!

文章开头,我们想来点一下题,什么是策略模式?

策略模式的定义:每个策略中定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

好吧,我已开始也是被这个定义吓尿了。简单地举个栗子说,就是你下班回家,可以走路、骑车、坐车、开车、开飞机等,每种方式都是一个策略,在代码里就可以将每个策略写成一个个的方法,方便管理。这样就不用使用一大堆判断语句了,难看而且不好维护。

我们今天讲的是技巧,在这里就不得不说到事件委托——又是一个高大威猛的概念(概念虽好,其实在代码里就很好理解,不信接着看)

没有场景的代码都是耍流氓!

场景很简单,就是点击“已有账号,立即登录”切换到登录,点击“还没有账号”切换到注册

有些小伙伴一下就明白了怎么回事,不就是个点击切换嘛!诶,是滴,就是这么简单,但我们就是喜欢吃猪蹄吃出熊掌的感觉😁

写两个简单的div代替一下(其中class中的hide代表隐藏的css):

<div id="login-box">
这是个登录框
   <span id="goToRegister">还没有账号?马上注册</span
</div>

<div id="register-box" class="hide">
这是个注册框
   <span id="goToLogin">已有账号,立即登录</span
</div>

善用jQuery的小伙伴们一下子就想到了该怎么写:

$('#goToRegister').click(function () {
            $('#login-box').addClass('hide')
                .siblings('#register-box').removeClass('hide');
        });
        $('#goToLogin').click(function () {
            $('#register-box').addClass('hide')
                .siblings('#login-box').removeClass('hide');
        });

不得不佩服jQuery,简单明了。但是这样写有一个很大的问题,就是页面如果有很多的点击事件的时候,难道也要去一个一个复制粘贴类似的代码吗?还是那句话——don't repeat youself!

还记得我们刚才提到过的事件委托吗?还不清楚什么是事件委托还是要去搜一下,简单的理解就是所有子元素的相同事件都委托到父元素。

$('body').on("click",function (e) {
            if (e.target.id === 'goToLogin') {
                $('#register-box').addClass('hide')
                    .siblings('#login-box').removeClass('hide');
            } else if (e.target.id === 'goToRegister') {
                $('#login-box').addClass('hide')
                    .siblings('#register-box').removeClass('hide');
            }
        })

是的,这就是事件委托,把两个点击事件都委托给body。为什么要用事件委托呢,一方面是好看(可读性高),不用像上面的代码一样复制那么多的事件代码;另一方面是性能,因为挂载事件的时候是很消耗性能的,一两个事件可能不觉得,一旦有个几十上百个事件(比如说列表)的时候,你就会脸上笑嘻嘻,心里妈卖批。

代码好像稍稍完善了一丢丢,但是!就像上面说的,一旦有很多的而且是不一样子元素的事件的时候,你就要写很多很多判断语句,这是我们万万不想看到的,这个时候我们就要想想有没有什么设计模式来解决此类问题。对,策略模式。

很明显这里有两种策略:跳到登录或者跳到注册

var cutOver = {
            goToLogin: function () { //跳到登录
                $('#register-box').addClass('hide')
                    .siblings('#login-box').removeClass('hide');
            },
            goToRegister: function () { //跳到注册
                $('#login-box').addClass('hide')
                    .siblings('#register-box').removeClass('hide');
            }
        };

说到策略这个词,我们不得不联想到执行者,那么在这里的执行者是谁呢?我们要写一个去执行策略的方法:

var eventProxy = function (command) {
            cutOver[command] && cutOver[command]();
            //command存在的时候才执行策略
        };

最后就是策略模式的事件委托:

$('body').on("click",function (e) {
            eventProxy(e.target.id);
        });

写到这里其实就算结束了。慢着!说好的技巧呢?聪明的你会注意到我在策略对象里的方法名其实是两个div的id。所以,最大的技巧既不是策略模式,也不是事件委托,而是这个相当于粘合剂一样的小技巧,是它把策略模式和事件委托很好的联系到一起。