设计模式(8)--组合模式

来源:互联网 发布:java预防死锁的方法 编辑:程序博客网 时间:2024/06/07 17:57

数据结构中有一种结构是树,树包含根节点、子节点、叶子结点,而组合模式就是专门用来处理类似树结构的设计模式,组成这棵树的节点和叶子是一个个对象,而组合模式却可以以统一对待叶子和节点。

要想统一对待,在面向对象中很难不想到抽象二字,只有站的高,面向高层处理,才有底气屏蔽底层细节,增加扩展性。

举个栗子:

   平常我们用的windows文件夹就是树结构的,文件夹里可以包含文件夹,文件夹里可以包含文件,这里文件夹代表容器,也就是节点,文件就代表叶子结点,不可包含其他。


组合模式UML类图如下所示:


解释:Folder和File_是Compotent的子类容易理解,但但Component和Folder的关联聚合关系怎么理解呢?Component是Folder和File_的抽象,但在这个树状结构中,Folder既能包含Folder,又能包含File_,也就是Folder包含他们的共同父类Component:Folder contains Conponent,体现在类图中的就是聚合关系。


下面以读取文件夹为例写一个组合模式实例小程序,注意读取文件夹会把他下面所有文件夹带文件读取一遍。

抽象组件类:

/**** * 抽象组件类,文件夹和文件的抽象类 * @author wjw * */public abstract class Component {public abstract void addComponent(Component component);public abstract void deleteComponent(Component component);public abstract Component getChild(int i);public abstract void read();}

文件夹类:


public class Folder extends Component{private String folderName;private List<Component> components = new ArrayList<Component>();public Folder(String folderName){this.folderName = folderName;}@Overridepublic void addComponent(Component component) {// TODO Auto-generated method stubcomponents.add(component);}@Overridepublic void deleteComponent(Component component) {// TODO Auto-generated method stubcomponents.remove(component);}@Overridepublic Component getChild(int i) {// TODO Auto-generated method stubreturn components.get(i);}@Overridepublic void read() {// TODO Auto-generated method stubSystem.out.println("读取=="+folderName+"==文件夹!");System.out.println("----begin "+folderName+"----");for (Component component : components) {component.read();}System.out.println("----end "+folderName+"----");}}

文件类:

public class File_ extends Component{private String fileName;public File_(String fileName){this.fileName = fileName;}@Overridepublic void addComponent(Component component) {// TODO Auto-generated method stubSystem.out.println("文件中不允许添加文件!");}@Overridepublic void deleteComponent(Component component) {// TODO Auto-generated method stubSystem.out.println("文件中不允许删除文件!");}@Overridepublic Component getChild(int i) {// TODO Auto-generated method stubSystem.out.println("文件中不允许读取文件!");return null;}@Overridepublic void read() {// TODO Auto-generated method stubSystem.out.println("读取--"+fileName+"--文件!");}}

Main类:

public class Main {public static void main(String[] args) {Component c1 = new Folder("C盘");Component c2 = new Folder("系统文件夹");Component c3 = new Folder("应用程序文件夹");Component c3_1 = new Folder("QQ文件夹");Component c3_2 = new Folder("MYSQL文件夹");Component c3_3 = new Folder("MSN文件夹");Component c4 = new Folder("资料文件夹");Component c4_1 = new Folder("音乐文件夹");Component c4_1_1 = new File_("海阔天空.mp3");Component c4_2 = new Folder("图片文件夹");Component c4_2_1 = new File_("aaa.jpg");Component c4_2_2 = new File_("bbb.png");c1.addComponent(c2);c1.addComponent(c3);c1.addComponent(c4);c3.addComponent(c3_1);c3.addComponent(c3_2);c3.addComponent(c3_3);c4.addComponent(c4_1);c4.addComponent(c4_2);c4_1.addComponent(c4_1_1);c4_2.addComponent(c4_2_1);c4_2.addComponent(c4_2_2);c1.read();}}


运行结果:

读取==C盘==文件夹!
----begin C盘----
读取==系统文件夹==文件夹!
----begin 系统文件夹----
----end 系统文件夹----
读取==应用程序文件夹==文件夹!
----begin 应用程序文件夹----
读取==QQ文件夹==文件夹!
----begin QQ文件夹----
----end QQ文件夹----
读取==MYSQL文件夹==文件夹!
----begin MYSQL文件夹----
----end MYSQL文件夹----
读取==MSN文件夹==文件夹!
----begin MSN文件夹----
----end MSN文件夹----
----end 应用程序文件夹----
读取==资料文件夹==文件夹!
----begin 资料文件夹----
读取==音乐文件夹==文件夹!
----begin 音乐文件夹----
读取--海阔天空.mp3--文件!
----end 音乐文件夹----
读取==图片文件夹==文件夹!
----begin 图片文件夹----
读取--aaa.jpg--文件!
读取--bbb.png--文件!
----end 图片文件夹----
----end 资料文件夹----
----end C盘----


组合模式说明:

如果我们程序要处理的是一个树形结构,且忽略整体与部分差异,可以考虑组合模式合适不合适。这里我们组件就两个,分的不太细,在具体编程中,也许组件种类很多,比如文件夹类型分为系统文件夹,普通文件夹,文件类型分为图片文件、文本文件、音频文件、视频文件等。这时我们面向抽象的优点再次显现出来了。对扩展开放。

总而言之,组合模式处理树


如有错误,欢迎指正

end


原创粉丝点击