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 Listchildren = new List (); 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 Listchildren = new List (); 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: 组合模式让客户可以一致地使用组合结构和单一个对象。