C# 实现组合模式的 3 种方式
|
admin
2025年6月13日 21:43
本文热度 50
|
前言
嗨,程序员小伙伴们,早上好!
今天跟大家分享设计模式中的组合模式,以及在 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 编辑过