ComPosite(组合)
关键词: 树
问题:
将对象组织成树形结构。【磁盘管理 公司组织】
意图:
将对象组合成树形结构以表示“部分-整体”的层次结构。
Composite使得用户对单个对象和组合对象的使用【具有一致性】。
适用性:
你想表示对象的部分-整体层次结构。
你希望用户忽略组合对象与单个对象的不同,
用户将统一地使用组合结构中的所有对象。
优点:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
组合模式包含以下主要角色。
抽象构件(Component)角色:
它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
树叶构件(Leaf)角色:
是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
树枝构件(Composite)角色 / 中间构件:
是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
实现类图:
抽象构件(Component)角色:公司
public abstract class EmployeeBase//公司
{
protected string strName;//人名
public int salary;//工资
//构造方法
public EmployeeBase(string name, int salarys)
{
strName = name;
this.salary = salarys;
}
//添加所管理的下属
abstract public void Add(EmployeeBase c);
//输出个人信息
abstract public void DumpContents();
//取出工资数
virtual public int GetSalary()
{
return salary;
}
}
树叶构件(Leaf)角色:管理人员
using System;
using System.Collections;
public class Manager : EmployeeBase//CEO 部门经理
{ //该管理人员管理下属
private ArrayList employees = new ArrayList();
//添加管理员工
override public void Add(EmployeeBase c)
{
employees.Add(c);
}
//返回当前管理人员数
public int Count
{
get { return employees.Count; }
}
//输出管理人员信息 和 所属下属人员信息
public override void DumpContents()
{
Console.WriteLine("{0} 工资:" + salary, strName);
foreach (EmployeeBase c in employees)
{
c.DumpContents();
}
}
//得到下属对象 可能是管理人员 也可能是员工
public EmployeeBase GetChild(int i)
{
return (EmployeeBase)employees[i];
}
public Manager(string s, int salary) : base(s, salary) { }
}
员工类
using System;
public class Employee : EmployeeBase//员工类
{
public override void Add(EmployeeBase c){ }
//输出个人信息
public override void DumpContents()
{
Console.WriteLine("{0} 工资:" + salary, strName);
}
//构造方法
public Employee(string s, int salary) : base(s, salary) { }
}
测试
using System;
class Program
{
static void Main(string[] args)
{ //初始化有9个员工 3个经理 1个CEO
Employee e1 = new Employee("z1", 10000);
Employee e2 = new Employee("z2", 10000);
Employee e3 = new Employee("z3", 10000);
Employee e4 = new Employee("z4", 10000);
Employee e5 = new Employee("z5", 10000);
Employee e6 = new Employee("z6", 10000);
Employee e7 = new Employee("z7", 10000);
Employee e8 = new Employee("z8", 10000);
Employee e9 = new Employee("z9", 10000);
Manager m1 = new Manager("m1 CEO", 40000);
Manager m2 = new Manager("m2 市场", 20000);
Manager m3 = new Manager("m2 研发", 30000);
Manager m4 = new Manager("m2 客服", 20000);
//CEO 管理 3个经理
m1.Add(m2);
m1.Add(m3);
m1.Add(m4);
//市场部经理管理 2个员工
m2.Add(e1);
m2.Add(e2);
//研发部经理管理 5个员工
m3.Add(e3);
m3.Add(e4);
m3.Add(e5);
m3.Add(e6);
m3.Add(e7);
//客服部经理管理 2个员工
m4.Add(e8);
m4.Add(e9);
//输出当前团队信息
m1.DumpContents();
//计算当前团队人员的总薪水
var totalSalary = GetAllSalary(m1);
Console.WriteLine("总计:" + totalSalary);
Console.ReadLine();
}
//计算管理人员 包括下属 的工资总数
public static int GetAllSalary(EmployeeBase emp)
{
var salary = emp.GetSalary();
//判断当前传进来对象 是否是管理人员
if (emp is Manager)
{
var mgr = emp as Manager;
for (int i = 0; i < mgr.Count; i++)
{
salary += GetAllSalary(mgr.GetChild(i));
}
}
return salary;
}
}
输出示例
设计模式------首页