再起航,我的学习笔记之JavaScript设计模式15(组合模式)

来源:互联网 发布:java socket心跳检测 编辑:程序博客网 时间:2024/03/29 03:40

组合模式

组合模式(Composite): 又称部分-整体模式,将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
如果有一个需求需要我们做一个门户网站,涉及到门户网站自然离不开文章列表,那么文章列表里又有文字列表,图片列表,图文列表,这么多种类的文章列表我们该怎么做呢?
首先我们可以创建一个文章列表的抽象父类,让其他的不同类型的文章列表都继承于这个类

var articles=function(){    //子组件容器    this.children=[];    //当前组件元素    this.element=null;}articles.prototype={    init:function(){        throw new Error("方法必须重写!");    },    add:function(){        throw new Error("方法必须重写!");    },    getElement:function(){        throw new Error("方法必须重写!");    }}

我们定义了这个接口抽象父类,下一步我们就是要实现所有的子类,但是我们要注意他们的层次关系,因为组合模式不仅仅是单层次组合,也可以是一个多层次的。
接着我们定义一个文章列表模块容器类

var Container=function(id,parent){    //构造函数继承父类    articles.call(this);    //模块ID    this.id=id;    //模块的父容器    this.parent=parent;    //构建初始化方法    this.init();}

原型式继承

function proObject(o){    //声明一个过渡函数对象    function Obj(){}    //过渡对象的原型继承父对象    Obj.prototype=o;    //返回过渡对象的一个实例,该实例的原型继承了父对象    return new Obj();}

寄生式组合式继承父类原型方法

function parasiticType(ParentClass,ChildClass){    //复制一份父类的原型保存在变量中     var parent=proObject(ParentClass.prototype);     //修正因为重写子类原型导致子类的constructor属性被修改     parent.constructor=ChildClass;     //设置子类的原型     ChildClass.prototype=parent;}parasiticType(articles,Container);

接着我们实现之前的初始化方法

Container.prototype.init=function(){    this.element=document.createElement('ul');    this.element.id=this.id;    this.element.className='articles-container'}

现在我们实现抽象父类中的方法

Container.prototype.add=function(child){    console.log(child);    //在子元素容器中插入子元素    this.children.push(child);    //插入当前组件元素树中    this.element.appendChild(child.getElement());    return this;}Container.prototype.getElement=function(){    return this.element;}Container.prototype.show=function(){    this.parent.appendChild(this.element);}

同样的下一层级的行成员集合类实现方法与之类似。

var Item=function(className){    articles.call(this);    this.className=className||"";    this.init();}parasiticType(articles,Item);Item.prototype.init=function(){    this.element=document.createElement('li');    this.element.className=this.className;}Item.prototype.add=function(child){    console.log(child);    //在子元素容器中插入子元素    this.children.push(child);    //插入当前组件元素树中    this.element.appendChild(child.getElement());    return this;}Item.prototype.getElement=function(){    return this.element;}

文章组合实体类实现方法也是一样的

var articlesGroup=function(className){    articles.call(this);    this.className=className||"";    this.init();}parasiticType(articles,articlesGroup);articlesGroup.prototype.init=function(){    this.element=document.createElement('div');    this.element.className=this.className;}articlesGroup.prototype.add=function(child){    //在子元素容器中插入子元素    this.children.push(child);    //插入当前组件元素树中    this.element.appendChild(child.getElement());    return this;}articlesGroup.prototype.getElement=function(){    return this.element;}

好了现在我们已经把所有子类成员创建出来了,不过光有这些容器类还不行,还需要有更底层的文章列表类。
图片文章列表

var ImageArticles=function(url,href,className){    articles.call(this);    this.url=url||"";    this.href=href||"#";    this.className=className||"normal";    this.init();}parasiticType(articles,ImageArticles);ImageArticles.prototype.init=function(){    this.element=document.createElement('a');    var img=new Image();    img.src=this.url;    this.element.appendChild(img);    this.element.className='image-news'+this.className;    this.element.href=this.href;}ImageArticles.prototype.add=function(){}    ImageArticles.prototype.getElement=function(){        return this.element;    }

文字文章列表

var TextArticles=function(text,href){    articles.call(this);    this.text=text||"";    this.href=href||"#";    this.init();}parasiticType(articles,TextArticles);TextArticles.prototype.init=function(){    this.element=document.createElement('a');    this.element.innerHTML=this.text;    this.element.href=this.href;    this.element.className="text";}TextArticles.prototype.add=function(){}TextArticles.prototype.getElement=function(){        return this.element;    }

现在所有的类我们都已经创建了,现在我们就要通过add方法来组合这些类

var Articles=new Container('articles',document.body);Articles.add(new Item('normal').add(    new ImageArticles('img/HBuilder.png','#','small')).add(new Item('normal').add(    new ImageArticles('img/HBuilder.png','#','small'))).add(new Item('normal').add(    new TextArticles('测试列表','#')    )).add(new Item('normal').add(    new TextArticles('测试列表2','#')    ))).show();

我们来看一看效果,这里我就偷懒不写样式了。我们可以看到,列表已经颇具雏形了。

现在我们创建的每一条文章列表都是一个独立的个体,互不影响,避免相互间的耦合,也增强了组合后的模块的复杂性,如果需要混搭,我们做出相应的组合就可以轻易的完成

总结

组合模式能够给我们提供一个清晰的组成结构。组合对象类通过继承同一个父类使其具有统一的方法,这样也方便了我们统一管理与使用,当然此时单体成员与组合体成员行为表现就比较一致了。这也就模糊了简单对象与组合对象的区别。有时这也是一种对数据的分级式处理。清晰而又方便我们队数据的管理与使用。

也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

欢迎转载,转载请注明作者,原文出处。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 11个月宝宝粘人怎么办 一岁宝宝脸冻了怎么办 2个月宝宝粘人怎么办 8个月宝宝粘人怎么办 9个月宝宝粘人怎么办 8个月婴儿粘人怎么办 4个月宝宝粘人怎么办 7个月宝宝粘人怎么办 8个月孩子太粘人怎么办 7个月宝宝太粘人怎么办 两岁宝宝粘人怎么办 孩子屁股被打了怎么办 长期被骂的孩子怎么办 儿童感冒咳嗽怎么办最有效 打了排卵针不排卵怎么办 孩孑上课不专心怎么办 4岁上课不听讲怎么办 孩子上课不认真听讲怎么办 孩子做什么都慢怎么办 7岁上课不听讲怎么办 打孩子脸肿了怎么办 一岁宝宝太调皮怎么办 怀孕早期喝了酒怎么办 怀孕期间喝了酒怎么办 一岁宝宝多动怎么办 3岁前儿童多动症怎么办 好动症的孩子该怎么办 18个月宝宝腹泻怎么办 8个月小孩发烧怎么办 八个月大宝宝发烧怎么办 8个月宝宝拉稀水怎么办 八个月宝宝38度怎么办 8个月的宝宝发烧怎么办 八个月大的宝宝拉肚子怎么办 9孩子上课坐不住怎么办 3岁宝宝太皮怎么办 4岁的宝宝多动症怎么办 小孩好动注意力不集中怎么办 乐扣加热变形了怎么办 3岁宝宝咳嗽厉害怎么办 六个月婴儿呕奶怎么办