1.组合模式定义:
将对象组合成树形结构以表示‘部分-整体’的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性
2.问题引入
- 总公司需要一套办公管理系统,拥有 人力资源,财务和运营等部门功能。
- 而总公司下面的华东,华北公司也拥有人力 资源和财务运行等部门。
- 总部,分部是树形结构的,不可以简单的平行管理
如何才能既满足层级管理的要求,又能够实现功能模块代码的复用?
3.问题分析
总公司的组织架构复用于分公司 可以抽象为 整体与部分可以被一致对待的问题
总公司相当于一刻大树,而下属分公司相当于一根树枝,而其下更小的办事处则是树枝的分支。而人力资源部,财务部则是大树上的树叶,也是一颗书的最低层级。树的不同层级都可以拥有叶子节点,因此无论是总公司的人力资源部还是办事处的人力资源部,都是整个树上的一个叶子节点【功能模块的复用】,其区别只在于其属于不同层级的父节点【实现了层级管理】。而组合模式,正是根据这一特性产生的。
4.代码实现
根节点(抽象类)
abstract class Component
{
protected string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
枝节点
class Composite : Component
{
private List<Component> children = new List<Component>();
public Composite(string name) : base(name) { }
public override void Add(Component c)
{
children.Add(c);
}
public override void Remove(Component c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine(new string('-', depth) + name);
foreach(Component component in children)
{
component.Display(depth + 2);
}
}
}
叶节点
class Leaf : Component
{
public Leaf(string name) : base(name) { }
public override void Add(Component c)
{
Console.WriteLine("不能够添加叶节点");
}
public override void Remove(Component c)
{
Console.WriteLine("不能够移除叶节点");
}
public override void Display(int depth)
{
Console.WriteLine(new string('-',depth) + name);
}
}
运行效果:
5.总结
5.1 何时使用?
- 需求中体现了部分与总体的结构关系
- 忽略组合对象和单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑用组合模式
实际上在ASP.Net中,所用的web控件的基类都是System.Web.UI.Contril,而Control基类中就有 Add 和 Remove方法,这就是典型的组合模式的应用。
参考:
- 《大话设计模式》 -作者: 程杰 出版年: 2007-12-1 出版社: 清华大学出版社