C# 实现组合模式的 3 种方式
				
									
					
					
						 | 
						
							
							admin 
							
							
								2025年6月13日 21:43
								本文热度 1520
							
							 
						 | 
					
					
				 
				前言
嗨,程序员小伙伴们,早上好!
今天跟大家分享设计模式中的组合模式,以及在 C# 中实现组合模式的 3 种方式。
话不多说,直接上正文。
核心思想
组合模式的核心思想是通过统一接口来处理单个对象(叶子节点)和对象组合(容器节点),使得客户端无需关心操作的是单个对象还是组合对象。
结构
- 抽象组件(Component) :定义一个接口,表示单个对象或组合对象的公共行为。
 - 叶子组件(Leaf) :实现抽象组件接口,表示叶子节点,没有子节点。
 - 组合组件(Composite) :实现抽象组件接口,表示组合节点,可以包含多个子节点。
 - 客户端代码:通过统一的接口操作单个对象和组合对象,隐藏内部结构。
 
如下图:
经典继承方式
using System;
using System.Collections.Generic;
// 组件抽象类或接口
public abstract class Component
{
    protected string name;
    public Component(string name)
    {
        this.name = name;
    }
    // 添加子组件
    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) : base(name)
    {
    }
    public override void Add(Component component)
    {
        // 叶子节点不能添加子组件
        Console.WriteLine("Cannot add to a leaf");
    }
    public override void Remove(Component component)
    {
        // 叶子节点不能移除子组件
        Console.WriteLine("Cannot remove from a leaf");
    }
    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) : base(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 (Component component in children)
        {
            component.Display(depth + 2);
        }
    }
}
// 使用
class Program
{
    static void Main(string[] args)
    {
        // 创建树结构
        Composite root = new Composite("Root");
        root.Add(new Leaf("Leaf A"));
        root.Add(new Leaf("Leaf B"));
        Composite comp = new Composite("Composite X");
        comp.Add(new Leaf("Leaf XA"));
        comp.Add(new Leaf("Leaf XB"));
        root.Add(comp);
        root.Add(new Leaf("Leaf C"));
        // 添加和移除叶子节点
        Leaf leaf = new Leaf("Leaf D");
        root.Add(leaf);
        root.Remove(leaf);
        // 递归显示树结构
        root.Display(1);
    }
}
2. 接口实现方式
using System;
using System.Collections.Generic;
// 组件接口
public interface IGraphic
{
    void Draw();
    void Add(IGraphic graphic);
    void Remove(IGraphic graphic);
    IGraphic GetChild(int index);
}
// 叶子节点实现
public class Circle : IGraphic
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
    public void Add(IGraphic graphic)
    {
        throw new NotImplementedException();
    }
    public void Remove(IGraphic graphic)
    {
        throw new NotImplementedException();
    }
    public IGraphic GetChild(int index)
    {
        throw new NotImplementedException();
    }
}
// 复合图形实现
public class Picture : IGraphic
{
    private List<IGraphic> graphics = new List<IGraphic>();
    public void Draw()
    {
        Console.WriteLine("Drawing a picture containing:");
        foreach (var graphic in graphics)
        {
            graphic.Draw();
        }
    }
    public void Add(IGraphic graphic)
    {
        graphics.Add(graphic);
    }
    public void Remove(IGraphic graphic)
    {
        graphics.Remove(graphic);
    }
    public IGraphic GetChild(int index)
    {
        return graphics[index];
    }
}
// 使用
class Program
{
    static void Main(string[] args)
    {
        // 创建复合图形
        Picture picture = new Picture();
        // 添加简单图形
        picture.Add(new Circle());
        picture.Add(new Circle());
        // 创建另一个复合图形
        Picture innerPicture = new Picture();
        innerPicture.Add(new Circle());
        // 添加到主图形中
        picture.Add(innerPicture);
        // 绘制整个图形结构
        picture.Draw();
    }
}
3. 泛型方式实现
using System;
using System.Collections.Generic;
// 通用组件接口
public interface IComponent<T> where T : IComponent<T>
{
    string Name { get; }
    void Add(T component);
    void Remove(T component);
    void Display(int depth);
}
// 叶子节点实现
public class Leaf : IComponent<Leaf>
{
    public string Name { get; }
    public Leaf(string name)
    {
        Name = name;
    }
    public void Add(Leaf component)
    {
        throw new InvalidOperationException("Cannot add to a leaf");
    }
    public void Remove(Leaf component)
    {
        throw new InvalidOperationException("Cannot remove from a leaf");
    }
    public void Display(int depth)
    {
        Console.WriteLine($"{new string('-', depth)}{Name}");
    }
}
// 复合组件实现
public class Composite : IComponent<Composite>
{
    private readonly List<Composite> children = new List<Composite>();
    public string Name { get; }
    public Composite(string name)
    {
        Name = name;
    }
    public void Add(Composite component)
    {
        children.Add(component);
    }
    public void Remove(Composite component)
    {
        children.Remove(component);
    }
    public void Display(int depth)
    {
        Console.WriteLine($"{new string('-', depth)}{Name}");
        foreach (var child in children)
        {
            child.Display(depth + 2);
        }
    }
}
// 使用示例
class Program
{
    static void Main(string[] args)
    {
        var root = new Composite("Root");
        var branch1 = new Composite("Branch 1");
        var branch2 = new Composite("Branch 2");
        branch1.Add(new Composite("Sub-branch 1.1"));
        branch1.Add(new Composite("Sub-branch 1.2"));
        branch2.Add(new Composite("Sub-branch 2.1"));
        root.Add(branch1);
        root.Add(branch2);
        root.Display(1);
    }
}
总结
经典继承方式 使用抽象基类定义组件公共接口,它结构清晰但不够灵活,新增操作需要修改基类,比较适合简单明确的层次结构。
接口实现方式 使用接口而非抽象类,支持多接口实现,更灵活,适合作为公共API的一部分。
泛型实现方式 可以创建类型特化的组件,支持更复杂的组件关系,但相应地灵活性更差,实现复杂度较高。
建议优先考虑接口实现方式,除非有特殊需求。
阅读原文:原文链接
该文章在 2025/6/14 16:51:45 编辑过