您的位置:首页 > Web前端 > JavaScript

Javascript乱弹设计模式系列(4) - 组合模式(Composite)

2009-01-15 22:23 363 查看
前言

博客园谈设计模式的文章很多,我也受益匪浅,包括TerryLee吕震宇等等的.NET设计模式系列文章,强烈推荐。对于我,擅长于前台代码的开发,对于设计模式也有一定的了解,于是我想结合Javascript来设计前台方面的“设计模式”,以对后台“设计模式”做个补充。开始这个系列我也诚惶诚恐,怕自己写得不好,不过我也想做个尝试,一来希望能给一些人有些帮助吧,二来从写文章中锻炼下自己,三来通过写文章对自己增加自信;如果写得不好,欢迎拍砖,我会虚心向博客园高手牛人们学习请教;如果觉得写得还可以,谢谢大家的支持了:)

组合模式比较简单,那么开始今天的文章。

概述

它又是部分-整体的模式,元素有两种形式,一种是简单元素,一种是复杂元素,其中复杂元素是简单元素的组成,所以客户程序要操作复杂元素时,有时候它并不想了解内部包括哪些简单元素,但是又想能够保持简单元素的简易操作性,于是,就有了组合模式,它可以抽象成一个树状结构,其中简单元素为叶子结点,而复杂元素为非叶子结点。

定义

组合模式允许你将对象组合成树形结构以表示“整体/部分”的层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

类图

Menu.js

function Menu(text, title, href) {

this.menuComponents = new Array();

this.text = text;

this.title = title;

this.href = href;

Interface.registerImplements(this, MenuComponent);

}

Menu.prototype = {

getValue : function() {

if(this.menuComponents.length == 0)

{

throw new Error(this.text + "菜单下没有子菜单");

}

var str = "<li class=\"Menu-WithChildren\" title=\"" + this.title + "\"><a class=\"Menu-Link\" href=\"" + this.href + "\">" + this.text + "</a>";

str += "<ul>";

for(var i = 0, len = this.menuComponents.length; i < len; i++)

{

str += this.menuComponents[i].getValue();

}

str += "</ul>";

return str;

},

add : function(component) {

this.menuComponents.push(component);

},

remove : function(component) {

for(var i = 0, len = this.menuComponents.length; i < len; i++)

{

if(this.menuComponents[i] == component)

{

this.menuComponents.splice(i,1);

break;

}

}

},

removeAt : function(index) {

if(this.menuComponents.length <= index)

{

this.menuComponents.splice(index, 1);

}

else

{

throw new Error("索引操作数组超过上限");

}

}

}

5. 接着添加一个Menu操作类MenuOpr:

var MenuOpr = {

list : new Array(),

add : function(component) {

this.list.push(component);

},

print : function(container) {

var str = "<ul class=\"Menu\">";

for(var i = 0, len = this.list.length; i < len; i++) {

str += this.list[i].getValue();

}

document.getElementById(container).innerHTML = str + "</ul>";

}

}

6. 最后利用组合模式编写调用代码:

var menu1 = new MenuItem("菜单1","菜单1","#");

var menu2 = new Menu("菜单2","菜单2","#");

var menu2_1 = new MenuItem("菜单2-1", "菜单2-1", "#");

var menu2_2 = new Menu("菜单2-2", "菜单2-2", "#");

var menu2_2_1 = new MenuItem("菜单2-2-1", "菜单2-2-1", "#");

var menu2_2_2 = new MenuItem("菜单2-2-2", "菜单2-2-2", "#");

var menu2_3 = new MenuItem("菜单2-3","菜单2-3","#");

menu2.add(menu2_1);

menu2.add(menu2_2);

menu2_2.add(menu2_2_1);

menu2_2.add(menu2_2_2);

menu2.add(menu2_3);

var menu3 = new Menu("菜单3","菜单3","#");

var menu3_1 = new MenuItem("菜单3-1","菜单3-1","#");

menu3.add(menu3_1);

var menu4 = new MenuItem("菜单4","菜单4","#");

MenuOpr.add(menu1);

MenuOpr.add(menu2);

MenuOpr.add(menu3);

MenuOpr.add(menu4);

MenuOpr.print("main_container");
main_container为一个div层的id,这里代码就不多说了,一看就看得懂的。

当然实现这个菜单还是有不少方法的,而我这肯定不是最优的,这里我只是提供一个利用组合模式的思路而已;

如果按照常规,你可以把MenuItem都整合到Menu上,即MenuItem都改为Menu,这样的代码,你是不是更喜欢点呢?

这个就留给大家自己研究吧!

最后,说下由于文中实例的菜单样式采用li:hover的方式来弹出下级菜单,由于这个方式对于IE7以下版本是无效的,所以这里引用了cssfriendly开源项目中的两个JS文件,MenuAdapter.js和AdapterUtils.js,所以把它们放进项目中引用进来,这样该菜单就兼容了IE7以下版本的浏览器。

附:源代码下载

[b]总结


该篇文章用Javascript设计组合模式的思路,实现一个菜单实例。

本篇到此为止,谢谢大家阅读



参考文献:《Head First Design Pattern》

本系列文章转载时请注明出处,谢谢合作!

相关系列文章:

Javascript乱弹设计模式系列(6) - 单件模式(Singleton)

Javascript乱弹设计模式系列(5) - 命令模式(Command)

Javascript乱弹设计模式系列(4) - 组合模式(Composite)

Javascript乱弹设计模式系列(3) - 装饰者模式(Decorator)

Javascript乱弹设计模式系列(2) - 抽象工厂以及工厂方法模式(Factory)

Javascript乱弹设计模式系列(1) - 观察者模式(Observer)

Javascript乱弹设计模式系列(0) - 面向对象基础以及接口和继承类的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: