组合模式(Composite Pattern)是一个结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端可以统一对待单个对象和对象集合。
在C#中,组合模式通常有以下几个要素:
- Component:定义所有类共有的接口,既可以是叶子节点也可以是组合节点的父类。
- Leaf:叶子节点类,表示没有子节点的对象。
- Composite:组合节点类,表示可以包含子节点的对象,它实现了
Component
接口并包含多个子组件。
使用示例
假设你正在设计一个图形库,图形可以是单一的图形(如圆形、矩形),也可以是包含多个图形的组合(如图形组合)。
1. 定义组件(Component)
using System;
using System.Collections.Generic;// 组件接口,定义了所有叶子和组合对象的共同操作
public interface IGraphic
{void Draw(); // 绘制图形void Add(IGraphic graphic); // 添加子图形(组合对象才有此方法)void Remove(IGraphic graphic); // 移除子图形
}
2. 定义叶子节点(Leaf)
叶子节点是图形中的基本元素,如Circle
和Rectangle
,这些元素不包含任何子图形。
// 叶子节点,表示单一的图形
public class Circle : IGraphic
{public void Draw(){Console.WriteLine("Drawing a Circle.");}public void Add(IGraphic graphic){throw new InvalidOperationException("Cannot add a child to a leaf.");}public void Remove(IGraphic graphic){throw new InvalidOperationException("Cannot remove a child from a leaf.");}
}public class Rectangle : IGraphic
{public void Draw(){Console.WriteLine("Drawing a Rectangle.");}public void Add(IGraphic graphic){throw new InvalidOperationException("Cannot add a child to a leaf.");}public void Remove(IGraphic graphic){throw new InvalidOperationException("Cannot remove a child from a leaf.");}
}
3. 定义组合节点(Composite)
组合节点可以包含多个子图形(无论是Leaf
还是其他Composite
对象)。
// 组合节点,表示可以包含多个图形的容器
public class GraphicGroup : IGraphic
{private List<IGraphic> _graphics = new List<IGraphic>();public void Draw(){Console.WriteLine("Drawing Group of Graphics:");foreach (var graphic in _graphics){graphic.Draw(); // 调用每个图形的Draw方法}}public void Add(IGraphic graphic){_graphics.Add(graphic); // 添加子图形}public void Remove(IGraphic graphic){_graphics.Remove(graphic); // 移除子图形}
}
4. 使用组合模式
public class Program
{public static void Main(string[] args){// 创建单个图形对象IGraphic circle = new Circle();IGraphic rectangle = new Rectangle();// 创建一个图形组,将多个图形组合成一个整体GraphicGroup group = new GraphicGroup();group.Add(circle);group.Add(rectangle);// 创建一个更大的组合GraphicGroup mainGroup = new GraphicGroup();mainGroup.Add(group); // 将一个组合加入到另一个组合中mainGroup.Add(new Circle()); // 也可以直接加入单一的图形// 绘制所有图形Console.WriteLine("Drawing individual elements:");circle.Draw();rectangle.Draw();Console.WriteLine("\nDrawing grouped elements:");group.Draw();Console.WriteLine("\nDrawing main group:");mainGroup.Draw();}
}
输出结果:
Drawing individual elements:
Drawing a Circle.
Drawing a Rectangle.Drawing grouped elements:
Drawing Group of Graphics:
Drawing a Circle.
Drawing a Rectangle.Drawing main group:
Drawing Group of Graphics:
Drawing Group of Graphics:
Drawing a Circle.
Drawing a Rectangle.
Drawing a Circle.
解释
-
Leaf(叶子节点):
Circle
和Rectangle
类是叶子节点,它们实现了IGraphic
接口,并且它们不允许添加或移除子图形,因为它们是单独的图形。 -
Composite(组合节点):
GraphicGroup
类是组合节点,它可以包含多个IGraphic
对象(包括其他组合节点和叶子节点)。它实现了IGraphic
接口,并且提供了Add
和Remove
方法来管理子图形。 -
客户端代码:在
Program
类中,创建了单个图形(如Circle
和Rectangle
),并通过组合(GraphicGroup
)将它们组织起来。客户端可以统一调用Draw
方法,无论它是操作单个图形还是多个图形的组合。
优点
- 统一接口:客户端代码对单个对象和组合对象的使用方式一致,简化了代码。
- 灵活性:允许递归地组合对象,形成树形结构,可以灵活地添加或移除子节点。
- 扩展性:如果以后需要支持更多的图形元素,只需在现有的结构基础上扩展,而无需修改现有代码。
这个示例展示了组合模式如何在现实应用中提供更大的灵活性和可扩展性,特别适合于层次化的树形结构场景。