一、组合模式
概述
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦
何时使用:1、想表示对象的部分-整体层次结构(树形结构) 2、希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
优缺点
优点:
- 组合模式通过递归的形式遍历组合对象,使得对象可以无限层次地嵌套。这样可以更加灵活地表示复杂的结构,并能够方便地对整个结构进行操作
- 通过组合模式,以统一的方式处理整体和部分,不需要关心当前操作的对象是叶节点还是组合节点,可以统一地进行操作
缺点:
- 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
1. 各个角色介绍
1.1 组件(Component)
- 定义了组合中所有对象的通用接口,可以是抽象类或接口。它声明了用于访问和管理子组件的方法,包括添加、删除、获取子组件等
1.2 叶子节点(Leaf)
- 表示组合中的叶子节点对象,叶子节点没有子节点。它实现了组件接口的方法,但通常不包含子组件
1.3 复合节点(Composite)
- 表示组合中的复合对象,复合节点可以包含子节点,可以是叶子节点,也可以是其他复合节点。它实现了组件接口的方法,包括管理子组件的方法
2. UML图
我们有一个类 Component 对象作为所有对象的通用接口,然后 Leaf、Composite 分别实现该接口,并通过 Composite 构建非叶子节点和叶子节点,形成树状图,并以中序遍历的形式输出
3. 具体例子和代码
角色分配
- Component:抽象组件
- Leaf:叶子节点(叶子节点下,无组件,继承Component)
- Composite:组合节点(继承Component)
3.1 抽象组件
- Component
package com.vinjcent.prototype.composite;import io.swagger.annotations.ApiModelProperty;/*** @author vinjcent* @description 抽象组件* @since 2024/3/11 22:16*/
public abstract class Component {@ApiModelProperty("组件名称")protected String name;public Component(String name) {this.name = name;}/*** 组件操作*/public abstract void operation();/*** 为当前组件添加组件** @param component 需要添加的组件*/public abstract void add(Component component);/*** 移除某一组件** @param component 需要移除的组件*/public abstract void remove(Component component);/*** 根据下标获取子组件** @param index 下标* @return 下标对应组件*/public abstract Component getChild(int index);}
3.2 叶子节点
- Leaf
package com.vinjcent.prototype.composite;/*** @author vinjcent* @description 叶子节点(叶子节点下,无组件)* @since 2024/3/11 22:20*/
public class Leaf extends Component {public Leaf(String name) {super(name);}public void operation() {System.out.println("Leaf " + name + " is performing operation.");}public void add(Component component) {// 在叶节点中无法添加子节点,可以选择抛出异常或忽略该操作throw new UnsupportedOperationException("Unsupported operation: add");}public void remove(Component component) {// 在叶节点中无法移除子节点,可以选择抛出异常或忽略该操作throw new UnsupportedOperationException("Unsupported operation: remove");}public Component getChild(int index) {// 叶节点没有子节点,返回null或抛出异常return null;}
}
3.3 组合节点
- Composite
package com.vinjcent.prototype.composite;import io.swagger.annotations.ApiModelProperty;import java.util.ArrayList;
import java.util.List;/*** @author vinjcent* @description 组合节点* @since 2024/3/11 22:44*/
public class Composite extends Component {@ApiModelProperty("子节点")private List<Component> children;public Composite(String name) {super(name);children = new ArrayList<>();}@Overridepublic void operation() {System.out.println("Composite " + name + " is performing operation.");for (Component child : children) {child.operation();}}@Overridepublic void add(Component component) {children.add(component);}@Overridepublic void remove(Component component) {children.remove(component);}@Overridepublic Component getChild(int index) {return children.get(index);}
}
3.4 测试主函数
package com.vinjcent.prototype.composite;/*** @author vinjcent* @description 组合模式* @since 2024/3/11 22:51:07*/
public class Main {public static void main(String[] args) {// 根节点Component root = new Composite("Root");// 叶子节点1、2Component leaf1 = new Leaf("L. one");Component leaf2 = new Leaf("L. two");// 子节点1Component node1 = new Composite("N. one");Component leaf3 = new Leaf("L. three");// 子节点2Component node2 = new Composite("N. two");Component leaf4 = new Leaf("L. four");// 为子节点添加叶子节点node1.add(leaf3);node2.add(leaf4);// 为根节点添加子节点、叶子节点root.add(leaf1);root.add(leaf2);root.add(node1);root.add(node2);// 输出结果,相当于中序遍历root.operation();}}
- 测试结果
4. 使用场景
- 部分、整体场景,如树形菜单,文件、文件夹的管理