组合模式又叫部分-整体模式,它将所有对象组合成树形结构。使得用户只需要操作最上层的接口,就可以对所有成员做相同的操作。
一个再好不过的例子就是 jquery 对象,大家都知道 1 个 jquery 对象其实是一组对象集合。比如在这样一个 HTML 页面
1 2 3 4 5 6 |
<body> <div> <span></span> <span></span> </div> </body> |
我们想取消所有节点上绑定的事件, 需要这样写
1 2 3 4 5 |
var allNodes = document.getElementsByTagName("*"); var len = allNodes.length; while( len-- ){ allNodes.unbind("*"); } |
但既然用了 jquery,就肯定不会再做这么搓的事情。我们只需要 $( 'body' ).unbind( '*' );
当每个元素都实现 unbind 接口, 那么只需调用最上层对象 $( 'body' ) 的 unbind, 便可自动迭代并调用所有组合元素的 unbind 方法.
再来个具体点的例子, 还是 dev.qplus.com 这个网站的即时验证表单。
注意下面那个修改资料的按钮,如果有任意一个 field 的验证没有通过,修改资料的按钮都将是灰色不可点的状态。 这意味着我们重新填写了表单内容后, 都得去校验每个 field, 保证它们全部 OK.
这代码不难实现.
1 2 3 |
if ( nameField.validata() && idCard.validata() && email.validata() && phone.validata() ){ alert ( "验证OK" ); } |
似乎我们用一个外观模式也能勉强解决这里条件分支堆砌的问题,但真正的问题是,我们并不能保证表单里 field 的数量,也许明天产品经理就让你删掉一个或者增加两个. 那么这样的维护方式显然不能被接受.
更好的实现是有一个 form.validata 函数, 它负责把真正的 validata 操作分发给每个组合对象.
form.validata 函数里面会依次遍历所有需要校验的 field. 若有一个 field 校验未通过, form.validata 都会返回 false. 伪代码如下.
1 2 3 4 5 6 7 8 |
form.validata = function(){ forEach( fields, function( index, field ){ if ( field.validata() === false ){ return false; } }) return true; } |
额 2016 年 4 月 24 日
….. 我并不觉得这是组合模式咯…..
【Javascript设计模式2】-简单工厂模式 | Tencent AlloyTeam 2012 年 10 月 25 日
[…] 组合模式 […]
【Javascript设计模式9】-策略模式 | Tencent AlloyTeam 2012 年 10 月 25 日
[…] 组合模式 […]
【Javascript设计模式3】-观察者模式 | Tencent AlloyTeam 2012 年 10 月 25 日
[…] 组合模式: http://www.alloyteam.com/2012/10/commonly-javascript-design-patterns-combined-mode/ […]
【Javascript设计模式17】- 状态模式 | Tencent AlloyTeam 2012 年 10 月 25 日
[…] 组合模式: http://www.alloyteam.com/2012/10/commonly-javascript-design-patterns-combined-mode/ […]
【Javascript设计模式1】-单例模式 | Tencent AlloyTeam 2012 年 10 月 24 日
[…] 组合模式: http://www.alloyteam.com/2012/10/commonly-javascript-design-patterns-combined-mode/ […]
【javascript设计模式12】-迭代器模式 | Tencent AlloyTeam 2012 年 10 月 24 日
[…] 组合模式: http://www.alloyteam.com/2012/10/commonly-javascript-design-patterns-combined-mode/ […]