设计模式(10)---组合模式
组合模式 Composite (结构型模式)
1.概述
组合模式:将多个对象组合成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,它是一种对象结构型模式。
文件夹有有文件,也可以有其他文件夹,这就是一种树形结构。一个软件界面的主面板上,有其他面板,和一些按钮,标签,其他面板上又包含着另一些按钮,这也是树形结构。
组合模式让用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致性地处理树形结构中的叶子节点和容器节点。
2.结构图
组合模式定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。
3.透明组合模式代码
1 package Transparent; 2 /* 3 * 抽象构件 4 */ 5 public interface Component { 6 public void add(Component file) ; 7 public void remove(Component file) ; 8 public void operation() ; 9 }
1 package Transparent; 2 /* 3 * 叶子构件 4 */ 5 public class TextFile implements Component { 6 7 private String name ; 8 public TextFile(String name) { 9 this.name = name ; 10 } 11 12 @Override 13 public void add(Component file) { 14 System.out.println("不支持该方法"); 15 16 } 17 18 @Override 19 public void remove(Component file) { 20 System.out.println("不支持该方法"); 21 22 } 23 24 @Override 25 public void operation() { 26 System.out.println("对文件"+name+"进行扫描"); 27 28 } 29 30 }
1 package Transparent; 2 3 import java.util.ArrayList; 4 5 public class Folder implements Component { 6 7 private String name ; 8 private ArrayList<Component> fileList=new ArrayList<Component>(); 9 10 public Folder(String name) { 11 this.name = name ; 12 } 13 14 @Override 15 public void add(Component file) { 16 fileList.add(file); 17 18 } 19 20 @Override 21 public void remove(Component file) { 22 fileList.remove(file); 23 24 } 25 26 @Override 27 public void operation() { 28 System.out.println("----对文件夹"+name+"进行扫描----"); 29 30 //递归调用 operation 方法 31 for (Object obj : fileList){ 32 ((Component)obj).operation(); 33 } 34 35 } 36 37 }
1 package Transparent; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 Component file1,file2,file3,folder1,folder2 ; 7 8 folder1 = new Folder("文件夹A") ; 9 folder2 = new Folder("文件夹B") ; 10 11 file1 = new TextFile("文件a"); 12 file2 = new TextFile("文件b"); 13 file3 = new TextFile("文件c"); 14 15 folder1.add(file1); 16 folder1.add(file2); 17 folder1.add(folder2); 18 folder2.add(file3); 19 20 folder1.operation(); 21 } 22 23 }
客户类再调用add方法时,不用考虑加入的是文件还是文件夹,一致性地处理树形结构中的叶子节点和容器节点。
如果需要扩展新的叶子构件类,容器构件类可以不用修改,符合开-闭原则。
4.透明组合模式与安全组合模式
以上代码属于透明组合模式,在抽象构件类Component中,声明了所有用来管理子对象的方法,包括add,remove,这样实现Compenent接口的类都具备了这些方法。
好处是对于客户类来说,叶子和非叶子没有区别,因为它们具备一致的接口。
坏处是对于叶子构件来说,它其实没有add这样的功能,实现这些方法是没有意义的。
安全组合模式:在Component类中不去声明add,remove这样的方法,而是在容器构件类中去声明所有用来管理子类对象的方法。
缺点:不够透明,客户端不得不使用容器类本身来声明容器构件对象,否则无法访问其中新增的add()、remove()等方法。客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。
在实际应用中,安全组合模式的使用频率较高高,在Java AWT中使用的组合模式就是安全组合模式。