99、23种设计模式之组合模式(8/23)

组合模式(Composite Pattern)作为23种经典设计模式之一,属于结构型模式,其核心价值在于统一处理树形结构中的单个对象与组合对象,通过定义一致的接口,使客户端无需区分操作的是叶子节点还是分支节点。

一、组合模式的核心概念

1.适用场景

  • 需要表示"部分-整体"层次结构(如文件系统、UI组件、组织架构)。
  • 希望客户端统一处理单个对象和组合对象,避免冗余的条件判断。
  • 支持递归操作(如遍历树形结构)。

2.核心角色

  • Component(抽象组件):定义叶子节点和分支节点的公共接口,声明管理子节点的方法(如Add、Remove)。
  • Leaf(叶子节点):表示单个对象,无子节点,实现Component接口但抛出异常或空实现管理子节点的方法。
  • Composite(分支节点):包含子节点(叶子或分支),实现Component接口并管理子节点的增删查。

二、C#实现方式

组合模式在C#中有两种典型实现方式,各有优缺点:

1. 透明式组合模式

  • 特点:在Component抽象类中声明所有管理子节点的方法(如Add、Remove),叶子节点和分支节点均实现这些方法(叶子节点抛出异常)。
  • 优点:客户端可一致处理所有节点,无需区分类型。
  • 缺点:叶子节点实现无意义的方法,可能引发运行时异常。
csharp 复制代码
// 抽象组件
public abstract class Component
{
    public string Name { get; set; }
    public abstract void Add(Component component);
    public abstract void Remove(Component component);
    public abstract void Display(int depth);
}

// 叶子节点
public class Leaf : Component
{
    public Leaf(string name) => Name = name;
    public override void Add(Component component) => 
        throw new InvalidOperationException("Leaf cannot add components.");
    public override void Remove(Component component) => 
        throw new InvalidOperationException("Leaf cannot remove components.");
    public override void Display(int depth) => 
        Console.WriteLine($"{new string('-', depth)}{Name}");
}

// 分支节点
public class Composite : Component
{
    private List<Component> _children = new List<Component>();
    public Composite(string name) => Name = name;
    public override void Add(Component component) => _children.Add(component);
    public override void Remove(Component component) => _children.Remove(component);
    public override void Display(int depth)
    {
        Console.WriteLine($"{new string('-', depth)}{Name}");
        foreach (var child in _children) child.Display(depth + 2);
    }
}

// 客户端代码
var root = new Composite("Root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
var composite = new Composite("Composite X");
composite.Add(new Leaf("Leaf XA"));
root.Add(composite);
root.Display(1);

2. 安全式组合模式

  • 特点:Component仅声明通用方法(如Display),管理子节点的方法(如Add、Remove)仅在Composite中定义。
  • 优点:避免叶子节点实现无意义方法,类型安全。
  • 缺点:客户端需区分节点类型,破坏透明性。
csharp 复制代码
// 抽象组件(仅声明通用方法)
public abstract class Component
{
    public string Name { get; set; }
    public abstract void Display(int depth);
}

// 叶子节点
public class Leaf : Component
{
    public Leaf(string name) => Name = name;
    public override void Display(int depth) => 
        Console.WriteLine($"{new string('-', depth)}{Name}");
}

// 分支节点(声明管理子节点的方法)
public class Composite : Component
{
    private List<Component> _children = new List<Component>();
    public Composite(string name) => Name = name;
    public void Add(Component component) => _children.Add(component);
    public void Remove(Component component) => _children.Remove(component);
    public override void Display(int depth)
    {
        Console.WriteLine($"{new string('-', depth)}{Name}");
        foreach (var child in _children) child.Display(depth + 2);
    }
}

// 客户端需区分类型调用方法
var composite = new Composite("Composite");
composite.Add(new Leaf("Leaf")); // 合法
var leaf = new Leaf("Leaf");
leaf.Add(new Leaf("Leaf"));     // 编译错误(类型安全)

三、组合模式的优缺点

1.优点

  • 简化客户端代码:统一处理单个对象和组合对象,减少条件判断。
  • 扩展性强:新增组件类型(如新图形)无需修改现有代码,符合开闭原则。
  • 支持递归:方便遍历树形结构(如计算文件夹大小)。

2.缺点

  • 过度使用导致复杂度增加:非层次结构场景强行使用会适得其反。
  • 性能问题:大型树形结构的递归遍历可能引发栈溢出,需优化为迭代或缓存结果。

四、典型应用场景

  • 图形编辑器:基本图形(圆、矩形)与组合图形(由多个基本图形组成)的统一绘制。
  • 文件系统:文件与文件夹的统一操作(如删除、复制)。
  • UI组件:按钮、文本框等控件与窗口的统一管理。
  • 组织架构:员工与部门的统一权限控制。

五、与其他模式的对比

  • 与装饰器模式区别:装饰器模式动态添加职责,组合模式构建树形结构。
  • 与外观模式区别:外观模式简化复杂子系统调用,组合模式统一处理树形结构节点。
相关推荐
爱学习的小熊猫_7 小时前
设计模式之命令模式
设计模式·命令模式
liang_jy1 天前
抽象工厂模式
android·设计模式·面试
liang_jy1 天前
工厂方法模式
android·设计模式·面试
郝学胜-神的一滴1 天前
策略模式:模拟八路军的抗日策略
开发语言·c++·程序人生·设计模式·策略模式
秋难降1 天前
结构型模式 “全家桶”:适配、装饰、代理…7 种模式让你的代码更 “有章法”
java·设计模式·程序员
ytadpole1 天前
揭秘设计模式:从UI按钮到Spring事件的观察者模式
设计模式
liang_jy1 天前
责任链模式
android·设计模式·面试
现在没有牛仔了1 天前
用Spring Boot+工厂+策略模式优雅解耦支付系统
java·后端·设计模式
钢铁男儿1 天前
C# 一个投资跟踪程序的设计与实现:面向对象与设计模式的深度解析
java·设计模式·c#