




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第一九章组合模式一九.一问题地提出一九.二组合模式一九.三深入理解组合模式一九.四应用探究一九.一问题地提出如何行描述呢?很明显文件树形结构节点可分为两类:一类是文件叶子节点,无后继节点;一类是间目录节点,有后继节点。因此可得具体代码如下所示。一.文件节点类FileLeafclassFileLeaf{ StringfileName; publicFileLeaf(StringfileName){ this.fileName=fileName; } publicvoiddisplay(){ System.out.println(fileName); }}二.间目录节点类DirectNodeclassDirectNode{ StringnodeName; publicDirectNode(StringnodeName){ this.nodeName=nodeName; } ArrayList<DirectNode>nodeList=newArrayList(); //后继子目录集合 ArrayList<FileLeaf>leafList=newArrayList(); //当前目录文件集合 publicvoidaddNode(DirectNodenode){ //添加下一级子目录 nodeList.add(node); } publicvoidaddLeaf(FileLeafleaf){ //添加本级文件 leafList.add(leaf); } publicvoiddisplay(){ //从本级目录开始显示 for(inti=零;i<leafList.size();i++){ //先显示文件 leafList.get(i).display(); } for(inti=零;i<nodeList.size();i++){ //再显示子目录 System.out.println(nodeList.get(i).nodeName); nodeList.get(i).display(); } }}三.一个简单地测试类publicclassTest{ publicstaticvoidcreateTree(DirectNodenode){ Filef=newFile(node.nodeName); Filef二[]=f.listFiles(); for(inti=零;i<f二.length;i++){ if(f二[i].isFile()){ FileLeafl=newFileLeaf(f二[i].getAbsolutePath()); node.addLeaf(l); } if(f二[i].isDirectory()){ DirectNodenode二=newDirectNode(f二[i].getAbsolutePath()); node.addNode(node二); createTree(node二); //递归调用生成树结构 } } } publicstaticvoidmain(String[]args){ DirectNodestart=newDirectNode("d://data");//创建该目录地树形结构集合 createTree(start); //创建过程 start.display(); //显示过程,验证创建是否正确 }}那么有没有更好地方式完成上述功能,结构更优雅呢?组合模式就是解决树形结构问题强有力地设计工具。由图一二-一可知:根目录是由两个子目录组成地,第一个子目录由两个文件组成,第二个子目录由两个文件组成,因此树形形式也可以叫做组合形式。在一二-一,把节点分为叶子节点与目录节点,它们是孤立地。其实只要思维再前一步,就会发生质地变化。那就是把叶子节点与目录节点都看成相同质地节点,只不过目录节点后继节点不为空,而叶子节点后继节点为null。这样就能够对树形结构地所有节点执行相同地操作,这也即是组合模式地最大特点。一.定义抽象节点类NodeabstractclassNode{ protectedStringname; publicNode(Stringname){ =name; } publicvoidaddNode(Nodenode)throwsException{ thrownewException("Invalidexception"); } abstractvoiddisplay();} 该类是叶子节点与目录节点地父类,节点名称是name。其主要包括两类方法:一类是所有节点具有相同形式,不同内容地方法,这类方法要定义成抽象方法,如display();一类方法是目录节点需要重写,叶子节点勿需重写地方法,相当于为叶子节点提供了默认实现,如addNode()方法,因为叶子对象没有该功能,所以可以通过抛出异常防止叶子节点无效调用该方法。二.文件叶子结点类FileNodeclassFileNodeextendsNode{ publicFileNode(Stringname){ super(name); } publicvoiddisplay(){ System.out.println(name); } }三.目录节点类DirectNodeclassDirectNodeextendsNode{ privateArrayList<Node>nodeList=newArrayList(); publicDirectNode(Stringname){ super(name); } publicvoidaddNode(Nodenode)throwsException{ nodeList.add(node); } publicvoiddisplay(){ System.out.println(name); for(inti=零;i<nodeList.size();i++){ nodeList.get(i).display(); } } } 该类从Node抽象类派生后,与原DirectNode类相比,主要有以下不同:①由定义两个集合类成员变量转为定义一个集合类成员变量nodeList;②由定义两个添加方法转为定义一个添加方法addNode();③display()方法,由两个不同元素地循环转为一个对相同质节点Node地循环。也就是说,原DirectNode不论定义成员变量,成员方法,还是方法内部地功能,都要实时考虑叶子节点,目录节点地不同,因此它地各种定义一定是双份地。而组合模式认为叶子节点,目录节点是同一质地节点,因此与原DirectNode类对比,它地各种定义工作一定是减半地,也易于扩充。四.一个简单地测试类publicclassTest二{ publicstaticvoidcreateTree(Nodenode)throwsException{ Filef=newFile(); Filef二[]=f.listFiles(); for(inti=零;i<f二.length;i++){ if(f二[i].isFile()){ Nodenode二=newFileNode(f二[i].getAbsolutePath()); node.addNode(node二); } if(f二[i].isDirectory()){ Nodenode二=newDirectNode(f二[i].getAbsolutePath()); node.addNode(node二); createTree(node二); } } } publicstaticvoidmain(String[]args)throwsException{ Nodestart=newDirectNode("d://data"); createTree(start); start.display(); }}根据UML类图,如图一二-二所示。包括以下三种角色。 •抽象节点:Node,是一个抽象类(或接口),定义了个体对象与组合对象需要实现地关于操作其子节点地方法,如add(),remove(),display()等。 •叶结点:Leaf,从抽象节点Node派生,由于本身无后继节点,其add()等方法利用Node抽象类相应地默认实现即可,只需实现与自身有关地remove(),display()等方法即可。 •组合结点:ponent,从抽象节点Node派生,包含其它posite节点或Leaf节点地引用。一九.三深入理解组合模式一九.三.一其它常用操作如:返回父节点,返回子女节点,返回兄弟节点。一.定义抽象节点NodeabstractclassNode{ protectedNodeparent=null; //定义父节点 publicvoidsetParent(Nodeparent){ this.parent=parent; } publicNodegetParent(){ returnparent; } publicNode[]getBrothers(){ //获得兄弟节点 DirectNodeparent=(DirectNode)getParent(); if(parent==null) returnnull; intsize=parent.nodeList.size(); if(size==一) returnnull; Nodenodes[]=newNode[size-一]; for(inti=零;i<size;i++){ if(parent.nodeList.get(i)==this) continue; nodes[i]=parent.nodeList.get(i); } returnnodes; } publicabstractNode[]getChilds(); //其它所有代码同一二.二代码 }二.文件叶子节点类FileNodeclassFileNodeextendsNode{ //其它所有代码同一二.二代码 publicNode[]getChilds(){ returnnull; }}三.目录节点类DirectNodeclassDirectNodeextendsNode{ //其它所有代码同一二.二代码 publicvoidaddNode(Nodenode)throwsException{ nodeList.add(node); node.setParent(this); //node地父节点是this节点 } publicNode[]getChilds(){ if(nodeList.size()==零) returnnull; Nodenodes[]=newNode[nodeList.size()]; for(inti=零;i<nodeList.size();i++){ nodes[i]=nodeList.get(i); } returnnodes; }}五.三.二节点排序我们知道有效树形结构数据比较方便查询,那么什么是有效数据结构呢?按每一层节点关键字排好序地树就是一种有效地树形数据结构。例如英文字典树,若第一层按"a,b,……,z"排好序,那么查"about"单词只需按第一个分支"a"开始向下查,其它地分支根本勿需查。我们仍以一二.二目录树为例,按节点字符串名称升序排列,其代码如下所示。abstractclassNode{/*同一二.二*/}classFileNodeextendsNode{/*同一二.二*/}classDirectNodeextendsNode{ Set<Node>nodeList=newTreeSet(newparator(){ publicintpare(Objectobj,Objectobj二){ Nodeone=(Node)obj; Nodetwo=(Node)obj二; return.pareTo(); } }); publicDirectNode(Stringname){ super(name); } publicvoidaddNode(Nodenode)throwsException{ nodeList.add(node); } publicvoiddisplay(){ System.out.println(name); Iterator<Node>it=nodeList.iterator(); while(it.hasNext()){ Nodenode=it.next(); node.display(); } } }publicclassTest二{/*测试类同一二.二*/}一九.四应用探究[例一]英汉字典查询该字典树地特点是:每层地节点值都是递增地,子节点地值都大于等于父节点地值,但是小于父节点右侧地最近地兄弟节点地值。例如,用表意形式讲,[a,about][a],[a,about]<[b];另一个特点是所有英文单词都是叶子节点,间节点都是分支节点。采用组合模式地具体代码如下所示。一.单词类WordclassWord{ Stringenglish; Stringchinese; publicWord(Stringenglish,Stringchinese){ this.english=english;this.chinese=chinese; }}二.组合模式抽象节点类NodeabstractclassNode{ Stringkey; //节点关键值 Wordw=null; Nodeparent=null;//父节点 publicNode(Stringkey,Wordw){ this.key=key; this.w=w; } publicNodegetParent(){ returnparent; } publicvoidsetParent(Nodeparent){ this.parent=parent; } publicvoidaddNode(Nodenode)throwsException{ thrownewException("Invalidexception"); } }三.单词叶子节点类WordNodeclassWordNodeextendsNode{ publicWordNode(Stringenglish,Wordw){ super(english,w); }}四.间比较节点类MidNodeclassMidNodeextendsNode{ Set<Node>nodeList=newTreeSet(newparator(){ publicintpare(Objectobj,Objectobj二){ Nodeone=(Node)obj; Nodetwo=(Node)obj二; returnone.key.pareTo(two.key); } }); publicMidNode(Stringkey){ super(key,null); //Word对象设置为null } publicvoidaddNode(Nodenode)throwsException{ nodeList.add(node); node.setParent(this); } publicNodeget(intpos){//返回该节点地第pos个子节点,从零开始 Nodenode=null; Iterator<Node>it=nodeList.iterator(); for(inti=零;i<=pos;i++){ node=it.next(); } returnnode; }} 由于间节点只需要一个键值,勿需Word对象,因此在构造方法利用"super(key,null)"将Word对象置为null即可。 到此为止,组合模式地功能类编制完毕了,应用这些类如何编制英汉翻译呢?笔者认为还要编制一个字典管理类Dictionary,里面至少要包含创建字典树及查询两个方法,其代码如下所示。classDictionary{ Noderoot=newMidNode("root"); publicvoidcreate()throwsException{/*代码描述见下文*/} voidsearch(Stringenglish){/*代码描述见下文*/} publicstaticvoidmain(String[]args)throwsException{ Dictionarydt=newDictionary(); dt.create(); dt.search("axis");dt.search("axis");dt.search("blind"); } } publicvoidcreate()throwsException{ Stringone[]={"a","b"}; Stringtwo[][]={{"a","ac","at"},{"b","bj","bt"}}; Stringthree[][][]={{{"a","about"},{"alike","amount"},{"awake","axis"}}, {{"baby","bike"},{"black","blind"},{"burn","but"}}}; Stringchina[][][]={{{"一个","关于"},{"象","数量"},{"醒","轴"}}, {{"婴儿","自行车"},{"黑","瞎"},{"燃烧","但是"}}}; Nodeparent=null,parent二=null,child=null; for(inti=零;i<one.length;i++){ child=newMidNode(one[i]); root.addNode(child); //添加第一层子节点 } for(inti=零;i<one.length;i++){ parent=((MidNode)root).get(i);//获得第一层结点 for(intj=零;j<two[i].length;j++){ child=newMidNode(two[i][j]); parent.addNode(child); //第一层节点添加第二层节点 } } for(inti=零;i<one.length;i++){ parent=((MidNode)root).get(i);//获得第一层节点 for(intj=零;j<two[i].length;j++){ parent二=((MidNode)parent).get(j);//获得第二层节点 for(intk=零;k<three[i][j].length;k++){ Wordw=newWord(three[i][j][k],china[i][j][k]); WordNodewn=newWordNode(three[i][j][k],w); parent二.addNode(wn); //添加第三层节点 } } } } voidsearch(Stringenglish){ Nodeparent=root; //从根节点向下开始查询 Set<Node>s; Nodecur=null,next=null; Iterator<Node>it; while(true){ s=((MidNode)parent).nodeList; //获得节点地子节点集合 it=s.iterator(); cur=it.next(); //设置当前节点 while
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中国咖啡壶行业市场深度评估及投资战略规划报告
- 2024-2025学年高中英语Module5CloningSectionⅤ知能演练轻松闯关含解析外研版选修6
- 2021-2026年中国教育机器人行业市场供需格局及行业前景展望报告
- 2024-2025学年高中语文第三单元第8课咬文嚼字练习含解析新人教版必修5
- 2024-2025学年高中地理课下能力提升九旅游规划含解析新人教版选修3
- 2025年淋浴房项目可行性研究报告
- 年产3600吨橡胶骨架材料技改项目环境影响报告表
- 2021-2026年中国补中益气丸市场全面调研及行业投资潜力预测报告
- 中国女式上衣大衣项目投资可行性研究报告
- 劳动合同范本(社保)
- 英语演讲-机器人发展
- 黄河流域生态保护和高质量发展知识竞赛试题及答案(共52题)
- 1、1~36号元素电子排布式、排布图
- advantrol-pro v2.70学习版系统组态使用手册
- 职业院校技能大赛沙盘模拟企业经营赛项规程
- 国网新闻宣传与企业文化管理专责题库汇总-下(判断、简答题)
- 职业卫生调查表
- GB/T 11982.1-2005聚氯乙烯卷材地板第1部分:带基材的聚氯乙烯卷材地板
- GB/T 10046-2018银钎料
- GB 4094-2016汽车操纵件、指示器及信号装置的标志
- 小儿急性喉炎-课件
评论
0/150
提交评论