1. 分公司不就是一部门吗?
B: 为一家在全国许多城市都有分销机构的大公司做办公管理系统,总部有人力资源部,财务,运营等。
B: 根据ID的不同区分。
A: 要求是树状结构,也就是组织结构,你倒好,搞成简单的平行结构。
A: 你有没有发现这种整体和部分的情况很多。
A: 人力资源部,财务部的管理功能可以复用于分公司。这其实就是整体和部分可以被一致对待的问题。
A: 总公司单做一棵树的根,那它的下属公司什么?
B: 是树的分支,各办事处的相关的职能部门由于没有分支了,所有可以理解为树叶。
A: 没有同一片叶子,但是同一颗树上的树叶的样子差不多。功能能复用到子公司,那么最好的办法就是,处理总公司还是子公司的财务管理功能的方法都是一样的。
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);
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
root.Add(new Leaf("Leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
Console.Read();
}
}
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("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
3. 透明方式与安全方式
A: 透明方式,也就是说在Component中声明所有用来管理对象的方法,其中包括Add,Remove等。这样实现Component接口的所有子类都具有Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的接口。但问题也很明显,因为叶子本身没有该功能,所有实现它没有意义。
A: 安全方式,就就是Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它。不过由于不够透明,所有树叶和树枝将不具有相同的接口,客服端的调用需要做相应的判断,带来不便。
4. 何时使用组合模式
A: 但你在需求中体现部分与整体层次(树状)的结构,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑组合模式了。
5. 公司管理系统
class Program
{
static void Main(string[] args)
{
ConcreteCompany root = new ConcreteCompany("北京总公司");
root.Add(new HRDepartment("总公司人力资源部"));
root.Add(new FinanceDepartment("总公司财务部"));
ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
comp.Add(new HRDepartment("华东分公司人力资源部"));
comp.Add(new FinanceDepartment("华东分公司财务部"));
root.Add(comp);
ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
comp1.Add(new HRDepartment("南京办事处人力资源部"));
comp1.Add(new FinanceDepartment("南京办事处财务部"));
comp.Add(comp1);
ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
comp2.Add(new HRDepartment("杭州办事处人力资源部"));
comp2.Add(new FinanceDepartment("杭州办事处财务部"));
comp.Add(comp2);
Console.WriteLine("\n结构图:");
root.Display(1);
Console.WriteLine("\n职责:");
root.LineOfDuty();
Console.Read();
}
}
abstract class Company
{
protected string name;
public Company(string name)
{
this.name = name;
}
public abstract void Add(Company c);//增加
public abstract void Remove(Company c);//移除
public abstract void Display(int depth);//显示
public abstract void LineOfDuty();//履行职责
}
class ConcreteCompany : Company
{
private List<Company> children = new List<Company>();
public ConcreteCompany(string name)
: base(name)
{ }
public override void Add(Company c)
{
children.Add(c);
}
public override void Remove(Company c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
foreach (Company component in children)
{
component.Display(depth + 2);
}
}
//履行职责
public override void LineOfDuty()
{
foreach (Company component in children)
{
component.LineOfDuty();
}
}
}
//人力资源部
class HRDepartment : Company
{
public HRDepartment(string name)
: base(name)
{ }
public override void Add(Company c)
{
}
public override void Remove(Company c)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 员工招聘培训管理", name);
}
}
//财务部
class FinanceDepartment : Company
{
public FinanceDepartment(string name)
: base(name)
{ }
public override void Add(Company c)
{
}
public override void Remove(Company c)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 公司财务收支管理", name);
}
}
6. 组合模式的好处
B: 组合模式定义了基本对象和组合对象类的层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象有可以被组合,这样不断的递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
B: 用户是不用关心到底是处理一个组合组件还是一个叶节点,也就用不着定义组合而写一些选择判断语句了。
A: 组合模式让客户可以一致地使用组合结构和单一个对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。