Java组合模式处理树形结构数据
组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次结构,以下是完整的实现示例:

基础接口定义
// 组件接口
public interface Component {
void operation();
void add(Component component);
void remove(Component component);
Component getChild(int index);
String getName();
double getPrice();
}
叶子节点实现
// 叶子节点 - 具体商品
public class Product implements Component {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public void operation() {
System.out.println("商品: " + name + ", 价格: " + price);
}
@Override
public void add(Component component) {
throw new UnsupportedOperationException("叶子节点不支持添加操作");
}
@Override
public void remove(Component component) {
throw new UnsupportedOperationException("叶子节点不支持删除操作");
}
@Override
public Component getChild(int index) {
throw new UnsupportedOperationException("叶子节点没有子节点");
}
@Override
public String getName() {
return name;
}
@Override
public double getPrice() {
return price;
}
}
组合节点实现
import java.util.ArrayList;
import java.util.List;
// 组合节点 - 商品分类
public class Category implements Component {
private String name;
private List<Component> components = new ArrayList<>();
public Category(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("分类: " + name);
System.out.println("包含以下商品/子分类:");
for (Component component : components) {
component.operation();
}
System.out.println("-------------------");
}
@Override
public void add(Component component) {
components.add(component);
}
@Override
public void remove(Component component) {
components.remove(component);
}
@Override
public Component getChild(int index) {
if (index >= 0 && index < components.size()) {
return components.get(index);
}
return null;
}
@Override
public String getName() {
return name;
}
@Override
public double getPrice() {
double totalPrice = 0;
for (Component component : components) {
totalPrice += component.getPrice();
}
return totalPrice;
}
// 获取所有子节点(包括递归)
public List<Component> getAllChildren() {
return new ArrayList<>(components);
}
// 获取分类下所有商品的总数
public int getProductCount() {
int count = 0;
for (Component component : components) {
if (component instanceof Product) {
count++;
} else if (component instanceof Category) {
count += ((Category) component).getProductCount();
}
}
return count;
}
}
使用示例
public class CompositePatternDemo {
public static void main(String[] args) {
// 创建根分类
Category root = new Category("网上商城");
// 创建电子分类
Category electronics = new Category("电子产品");
root.add(electronics);
// 创建手机子分类
Category phones = new Category("手机");
electronics.add(phones);
// 添加手机产品
phones.add(new Product("iPhone 15", 6999.00));
phones.add(new Product("华为Mate 60", 5999.00));
phones.add(new Product("三星Galaxy S24", 4999.00));
// 创建电脑子分类
Category computers = new Category("电脑");
electronics.add(computers);
// 添加电脑产品
computers.add(new Product("MacBook Pro", 12999.00));
computers.add(new Product("ThinkPad X1", 9999.00));
// 创建服饰分类
Category clothing = new Category("服饰");
root.add(clothing);
// 添加服饰产品
clothing.add(new Product("T恤", 199.00));
clothing.add(new Product("牛仔裤", 399.00));
clothing.add(new Product("运动鞋", 599.00));
// 测试操作
System.out.println("=== 展示所有商品 ===");
root.operation();
System.out.println("\n=== 计算总价 ===");
System.out.println("电子分类总价: " + electronics.getPrice());
System.out.println("服饰分类总价: " + clothing.getPrice());
System.out.println("商城总价: " + root.getPrice());
System.out.println("\n=== 商品数量统计 ===");
System.out.println("电子分类商品数量: " + electronics.getProductCount());
System.out.println("服饰分类商品数量: " + clothing.getProductCount());
System.out.println("商城总商品数量: " + root.getProductCount());
System.out.println("\n=== 遍历叶子节点 ===");
traverseTree(root, 0);
}
// 递归遍历树形结构
private static void traverseTree(Component component, int depth) {
StringBuilder indent = new StringBuilder();
for (int i = 0; i < depth; i++) {
indent.append(" ");
}
if (component instanceof Product) {
System.out.println(indent + "📦 " + component.getName() + " - ¥" + component.getPrice());
} else if (component instanceof Category) {
System.out.println(indent + "📁 " + component.getName());
Category category = (Category) component;
for (Component child : category.getAllChildren()) {
traverseTree(child, depth + 1);
}
}
}
}
更高级的实现 - 使用泛型
// 泛型版本的组件接口
public interface TreeNode<T> {
T getData();
void addChild(TreeNode<T> child);
void removeChild(TreeNode<T> child);
List<TreeNode<T>> getChildren();
boolean isLeaf();
void accept(Visitor<T> visitor);
}
// 访问者模式接口
public interface Visitor<T> {
void visit(LeafNode<T> leaf);
void visit(CompositeNode<T> composite);
}
// 叶子节点
public class LeafNode<T> implements TreeNode<T> {
private T data;
public LeafNode(T data) {
this.data = data;
}
@Override
public T getData() {
return data;
}
@Override
public void addChild(TreeNode<T> child) {
throw new UnsupportedOperationException("叶子节点不能添加子节点");
}
@Override
public void removeChild(TreeNode<T> child) {
throw new UnsupportedOperationException("叶子节点不能删除子节点");
}
@Override
public List<TreeNode<T>> getChildren() {
return Collections.emptyList();
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public void accept(Visitor<T> visitor) {
visitor.visit(this);
}
}
// 组合节点
public class CompositeNode<T> implements TreeNode<T> {
private T data;
private List<TreeNode<T>> children = new ArrayList<>();
public CompositeNode(T data) {
this.data = data;
}
@Override
public T getData() {
return data;
}
@Override
public void addChild(TreeNode<T> child) {
children.add(child);
}
@Override
public void removeChild(TreeNode<T> child) {
children.remove(child);
}
@Override
public List<TreeNode<T>> getChildren() {
return new ArrayList<>(children);
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public void accept(Visitor<T> visitor) {
visitor.visit(this);
for (TreeNode<T> child : children) {
child.accept(visitor);
}
}
}
实际应用场景
文件系统结构
// 文件系统示例
public class FileSystemExample {
public static void main(String[] args) {
Component root = new Category("root");
Component documents = new Category("documents");
root.add(documents);
Component images = new Category("images");
root.add(images);
documents.add(new Product("report.docx", 1024));
documents.add(new Product("notes.txt", 512));
images.add(new Product("photo1.jpg", 2048));
images.add(new Product("photo2.jpg", 1536));
// 使用访问者模式计算总大小
root.operation();
}
}
公司组织结构
// 公司组织结构示例
public class CompanyStructureExample {
public static void main(String[] args) {
Component company = new Category("总公司");
Component development = new Category("开发部");
company.add(development);
Component sales = new Category("销售部");
company.add(sales);
// 添加员工(叶子节点)
development.add(new Product("张三", 15000));
development.add(new Product("李四", 18000));
sales.add(new Product("王五", 12000));
sales.add(new Product("赵六", 13000));
// 计算总薪资
System.out.println("公司总薪资: " + company.getPrice());
}
}
最佳实践和注意事项
-
透明性与安全性:可以在接口中定义所有方法,但在叶子节点中抛出异常(透明方式),或者将add/remove方法放在Composite类中(安全方式)
-
缓存优化:对于频繁访问的树形结构,可以缓存计算结果
public class CachedCategory extends Category {
private Double cachedPrice;
private boolean isDirty = true;
@Override
public double getPrice() {
if (isDirty) {
cachedPrice = super.getPrice();
isDirty = false;
}
return cachedPrice;
}
@Override
public void add(Component component) {
super.add(component);
isDirty = true;
}
}
-
递归深度控制:处理大型树形结构时注意递归深度,考虑使用栈代替递归
-
线程安全:多线程环境下需要使用同步机制
组合模式非常适合处理树形结构数据,提供了统一的接口来操作单个对象和组合对象,使得客户端代码更加简洁和灵活。