一、什么是组合模式
标签:总结,组合,void,AbstractFile,System,fileName,add,设计模式,public From: https://www.cnblogs.com/lxh-666/p/17818910.html组合模式也成为整体部分模式,是一种结构型设计模式。它将对象组合成树形的层次结构,用来表示“整体-部分”的关系。通过组合模式,我们可以使用相同的方式处理单个对象和多个对象组合。
二、角色组成
- 组件(Component):定义组合模式中所有对象共有的方法和属性。
- 叶子节点(Leaf):叶子节点对象,也是组合中没有子节点的对象。
- 组合节点(Composite):表示组合中的容器对象,该对象包含其他子节点。
三、优缺点
优点:通过组合模式,可以使客户端统一处理单个对象和组合对象,并且不用区分类型,简化了客户端代码的复杂性。
在无需修改现有的代码情况下,可以很容易地增减新的组件类型,更加灵活。
组合对象和单个对象之间的一致性接口可以使代码更易复用
缺点:可能限制组件的类型:组合模式要求组件和叶子节点具有相同的接口,这可能会限制组件的类型。例如,所有的组件都必须实现相同的操作,即使某些组件并不需要这些操作。
对某些操作的不支持:在组合模式中,对于某些操作,可能只有叶子节点能够支持,而组合对象不能够支持。这可能需要在设计时进行权衡。
可能增加系统复杂性:虽然组合模式可以简化客户端代码,但在另一方面,它也引入了新的类和关系,可能增加了系统的复杂性。在一些简单的情况下,使用组合模式可能会显得过于繁琐。
四、应用场景
4.1 生活场景
古代皇帝:皇帝治理国家不可能具体到某一个人,所以设置了很多机构,比如三省六部,这些机构下面又有很多小的组织,它们共同治理这个国家。
公司:一个公司下面有很多小部门,每个部门下面又分好几个组,有可能再细点每个组又分为职业不同的人(前端、测试、开发、运维)。
文件:比如C盘、D盘下面有很多文件夹,文件夹里面又有很多文件或文件夹。
4.2 java场景
HashMap:putAll()传入的是Map对象,Map就是一个组件,而HashMap就是一个组合节点,HashMap中的Node节点就是叶子节点。同理,ArrayList对象也有addAll()方法。
Java AWT和SWING:对于Button和Checkbox是叶子节点,Container是组合节点。
五、代码实现
下面以算数表达式为例,解释一下组合模式。我们可以把算数表达式看作是一个树状结构,由操作符和操作数组成。组件(Component):Expression
叶子节点(Leaf):AddOperator、MulOperator、Number
组合节点(Composite):Operator[实验任务一]:组合模式
用透明组合模式实现教材中的“文件夹浏览”这个例子。
- 实例代码如下
//AbstractFile.java public abstract class AbstractFile { public abstract void add(AbstractFile element); public abstract void remove(AbstractFile element); public abstract void display(); } public class Client { public static void main(String a[]) { AbstractFile obj1,obj2,obj3,obj4; Folder plate1,plate2,plate3; obj1=new ImageFile("a.jpg"); obj2=new TextFile("b.txt"); plate1=new Folder("Image_Text"); plate1.add(obj1); plate1.add(obj2); obj3=new VideoFile("c.mp4"); plate2=new Folder("Image_Video"); plate2.add(obj1); plate2.add(obj3); obj4=new ImageFile("d.jpg"); plate3=new Folder("Image_Text_Video_Folder"); plate3.add(plate1); plate3.add(plate2); plate3.add(obj4); plate3.display(); } } import java.util.*; public class Folder extends AbstractFile { private String fileName; private ArrayList<AbstractFile> fileList=new ArrayList(); public Folder(String filename) { this.fileName=new String(); this.fileName=filename; } public void add(AbstractFile element) { fileList.add(element); System.out.println("add Folder"); } public void remove(AbstractFile element) { fileList.remove(element); System.out.println("remove Folder"); } public void display() { System.out.println(fileName); for(Object object:fileList) { ((AbstractFile)object).display(); } System.out.println("****Folder display****"); } } public class ImageFile extends AbstractFile { private String fileName; public ImageFile(String filename) { this.fileName=new String(); this.fileName=filename; } public void add(AbstractFile element) { System.out.println("add ImageFile"); } public void remove(AbstractFile element) { System.out.println("remove ImageFile"); } public void display() { System.out.print(fileName); System.out.println(" ImageFile"); } } public class TextFile extends AbstractFile { private String fileName; public TextFile(String filename) { this.fileName=new String(); this.fileName=filename; } public void add(AbstractFile element) { System.out.println("add TextFile"); } public void remove(AbstractFile element) { System.out.println("remove TextFile"); } public void display() { System.out.print(fileName); System.out.println(" TextFile"); } } public class VideoFile extends AbstractFile { private String fileName; public VideoFile(String filename) { this.fileName=new String(); this.fileName=filename; } public void add(AbstractFile element) { System.out.println("add VideoFile"); } public void remove(AbstractFile element) { System.out.println("remove VideoFile"); } public void display() { System.out.print(fileName); System.out.println(" VideoFile"); } }