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;
}
}
-
递归深度控制:处理大型树形结构时注意递归深度,考虑使用栈代替递归
-
线程安全:多线程环境下需要使用同步机制
组合模式非常适合处理树形结构数据,提供了统一的接口来操作单个对象和组合对象,使得客户端代码更加简洁和灵活。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播