一.组合模式简述
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
UML图:
二.代码示例
我们的目标要实现下图的组织架构关系:
分析得知:Composite对象(有子节点)为:LDG科技公司,产品部,业务部,研发部,其余为Leaf对象(没有子节点)
抽象类代码:
public abstract class AbstractDepartment
{
/// <summary>
/// 部门名称
/// </summary>
protected string _departmentName;
public AbstractDepartment(string departmentName)
{
_departmentName = departmentName;
}
/// <summary>
/// 添加子节点的方法
/// </summary>
public abstract void AddChildren(AbstractDepartment company);
/// <summary>
/// 删除子节点的方法
/// </summary>
public abstract void RemoveChildren(AbstractDepartment company);
/// <summary>
/// 获取子节点数据
/// </summary>
public abstract List<AbstractDepartment> GetChildren();
/// <summary>
/// 获取部门名称
/// </summary>
public abstract string GetdepartmentName();
}
Leaf类代码:
/// <summary>
/// Leaf类
/// </summary>
public class LeafDepartment : AbstractDepartment
{
public LeafDepartment(string departmentName)
: base(departmentName)
{
}
public override void AddChildren(AbstractDepartment company)
{
throw new Exception("没有子节点,不能AddChild");
}
public override List<AbstractDepartment> GetChildren()
{
return null;
}
public override void RemoveChildren(AbstractDepartment company)
{
throw new Exception("没有子节点,不能RemoveChildren");
}
public override string GetdepartmentName()
{
return this._departmentName;
}
}
Composite类代码:
/// <summary>
/// Composite类
/// </summary>
public class CompositeDepartment : AbstractDepartment
{
private List<AbstractDepartment> list = new List<AbstractDepartment>();
public CompositeDepartment(string departmentName)
: base(departmentName)
{
}
public override void AddChildren(AbstractDepartment department)
{
list.Add(department);
}
public override void RemoveChildren(AbstractDepartment department)
{
list.Remove(department);
}
public override List<AbstractDepartment> GetChildren()
{
return list;
}
public override string GetdepartmentName()
{
return _departmentName;
}
}
运行结果–>递归输出树形结构:
递归代码:
public static void FindChildren(AbstractDepartment acompositeDepartment,int intA)
{
if (acompositeDepartment.GetChildren() == null)
{
//说明没有子节点
}
else
{
//说明有子节点
foreach (var item in acompositeDepartment.GetChildren())
{
for (int i = 0; i < intA; i++)
{
Console.Write("--");
}
Console.WriteLine($"{item.GetdepartmentName()}");
FindChildren(item,intA+1);
}
}
}
三.总结
意图: 将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决: 它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决: 树枝和叶子实现统一接口,树枝内部组合该接口。
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点: 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。