看到组合模式,真的是有一种很开心的感觉。
一.看实例需求
为什么会这么说呢,请看下面的例子:如果有一个项目,为一家在全国许多城市都有分销机构的大公司做办公管理系统,总部包括人力资源/财务/运营等部门,名下的分公司或办事处就上述部门的功能也要有,并且总部,分部,办事处这些都是有组织结构的,不可以平行管理。如下图:
二.解方法利弊
首先,简单的复制是最糟糕的设计
其次,共享功能到各个分公司,即总部/分部/办事处共用一套代码
但是很悲催,上述的两个方法均被毙掉!其一就不用多说了,这样的实现实在是没有意义的,不能为了敲代码而敲代码!其二,也不能满足客户的要求:总部/分部/办事处呈树状结构,是有组织结构的,而不可以平行管理,所以也不可取。
三.组合模式
其实上述情况就是部分与整体的关系,上述情况,虽然有组织结构,但是功能是一样的,所以在这里实际就是整体与部分可以被一致对待的问题。
组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
如下结构图:
四.树形结构-组合模式代码实现
具体实现代码如下(树形结构,根/分枝/叶结点)
namespace SJ_公司分公司_组合模式_树形结构实现_
{
class Program
{
static void Main(string[] args)
{
//生成树根root,根上长出两片叶子,leafA和leafB
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
//根上长出分枝Composite X,分枝上也有两叶LeafXA和LeafXB
Composite comp = new Composite("Composite X");
comp.Add(new Leaf ("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp );
//在Composite X上再长出分枝CompositeXY ,其分枝上也有两叶leafXYA和leafXYB
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
//根部又长出两叶leafC和leafD,可惜leafD没有长牢,被风吹走了
root.Add(new Leaf("Leaf C "));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);//显示大树的样子
Console.Read();
}
//组合模式:即将对象组合成树形结构以表示“部分-整体”的层次结构
//虚拟类,Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件
abstract class Component
{
protected string name;
public Component(string name)
{
this.name = name;
}
//通常用Add和Remove方法类提供增加或移除树叶或树枝的功能
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
//叶结点(Leaf),叶结点没有子节点
class Leaf : Component
{
public Leaf(string name)
: base(name)
{ }
public override void Add(Component c)
{
//由于叶结点没有再增加分枝和树叶,所以Add和Remove方法没有实现的意义,但这样做可以消除叶结点和枝节点对象在抽象层次的区别,
//他们具备完全一致的接口
Console.WriteLine("不能为叶结点再次增加分枝和树叶");
}
//同上
public override void Remove(Component c)
{
Console.WriteLine("Can't remove from a leaf");
}
public override void Display(int depth)
{
//叶结点的具体方法,此处是显示其名称和级别
Console.WriteLine(new string('-', depth) + name);
}
}
//枝节点的行为(Composite)用来存储子部件,在Component接口中实现与子部件有关的操作,比如Add和Remove操作
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);
}
}
}
}
}