/// <summary> /// Summary description for AbstractEmployee. /// 20220918 /// geovindu,Geovin Du,涂聚文 ///Composite Patterns 组合模式 /// /// </summary> public interface AbstractEmployee { /// <summary> /// get current salary /// </summary> /// <returns></returns> float getSalary(); /// <summary> /// get name /// </summary> /// <returns></returns> string getName(); /// <summary> /// true if leaf /// </summary> /// <returns></returns> bool isLeaf(); /// <summary> /// add subordinate /// </summary> /// <param name="nm"></param> /// <param name="salary"></param> void add(string nm, float salary); /// <summary> /// add subordinate /// </summary> /// <param name="emp"></param> void add(AbstractEmployee emp); /// <summary> /// get subordinates /// </summary> /// <returns></returns> IEnumerator getSubordinates(); /// <summary> /// get child /// </summary> /// <returns></returns> AbstractEmployee getChild(); /// <summary> /// get salaries of all /// </summary> /// <returns></returns> float getSalaries(); /// <summary> /// get Boss /// </summary> /// <returns></returns> AbstractEmployee getBoss(); }
/// <summary> /// Summary description for EmpNode. /// 20220918 /// geovindu,Geovin Du,涂聚文 ///Composite Patterns 组合模式 /// </summary> public class Employee : AbstractEmployee { protected float salary; protected string name; protected AbstractEmployee parent; protected ArrayList subordinates; /// <summary> /// /// </summary> /// <param name="parnt"></param> /// <param name="nm"></param> /// <param name="salry"></param> public Employee(AbstractEmployee parnt, string nm, float salry) { subordinates = new ArrayList(); name = nm; salary = salry; parent = parnt; } /// <summary> /// /// </summary> /// <returns></returns> public AbstractEmployee getBoss() { return parent; } /// <summary> /// /// </summary> /// <returns></returns> public float getSalary() { return salary; } /// <summary> /// /// </summary> /// <returns></returns> public string getName() { return name; } /// <summary> /// /// </summary> /// <returns></returns> public bool isLeaf() { return subordinates.Count == 0; } /// <summary> /// /// </summary> /// <param name="nm"></param> /// <param name="salary"></param> public virtual void add(string nm, float salary) { throw new Exception("No subordinates in base employee class"); } /// <summary> /// /// </summary> /// <param name="emp"></param> public virtual void add(AbstractEmployee emp) { throw new Exception("No subordinates in base employee class"); } /// <summary> /// /// </summary> /// <returns></returns> public IEnumerator getSubordinates() { return subordinates.GetEnumerator(); } public virtual AbstractEmployee getChild() { return null; } /// <summary> /// /// </summary> /// <returns></returns> public float getSalaries() { float sum; AbstractEmployee esub; //get the salaries of the boss and subordinates sum = getSalary(); IEnumerator enumSub = subordinates.GetEnumerator(); while (enumSub.MoveNext()) { esub = (AbstractEmployee)enumSub.Current; sum += esub.getSalaries(); } return sum; } }
/// <summary> /// Summary description for Boss. /// 20220918 /// geovindu,Geovin Du,涂聚文 ///Composite Patterns 组合模式 /// </summary> public class Boss : Employee { /// <summary> /// /// </summary> /// <param name="parnt"></param> /// <param name="name"></param> /// <param name="salary"></param> public Boss(AbstractEmployee parnt, string name, float salary) : base(parnt, name, salary) { } /// <summary> /// /// </summary> /// <param name="parnt"></param> /// <param name="emp"></param> public Boss(AbstractEmployee parnt, AbstractEmployee emp) : base(parnt, emp.getName(), emp.getSalary()) { } /// <summary> /// /// </summary> /// <param name="nm"></param> /// <param name="salary"></param> public override void add(string nm, float salary) { AbstractEmployee emp = new Employee(this, nm, salary); subordinates.Add(emp); } /// <summary> /// /// </summary> /// <param name="emp"></param> public override void add(AbstractEmployee emp) { subordinates.Add(emp); } /// <summary> /// /// </summary> /// <returns></returns> public override AbstractEmployee getChild() { bool found; AbstractEmployee tEmp = null; IEnumerator esub; if (getName().Equals(getName())) return this; else { found = false; esub = subordinates.GetEnumerator(); while (!found && esub.MoveNext()) { tEmp = (AbstractEmployee)esub.Current; found = (tEmp.getName().Equals(name)); if (!found) { if (!tEmp.isLeaf()) { tEmp = tEmp.getChild(); found = (tEmp.getName().Equals(name)); } } } if (found) return tEmp; else return new Employee(null, "New person", 0); } } }
/// <summary> /// Summary description for EmpNode. /// 20220918 /// geovindu,Geovin Du,涂聚文 ///Composite Patterns 组合模式 /// </summary> public class EmpNode : TreeNode { private AbstractEmployee emp; /// <summary> /// /// </summary> /// <param name="aemp"></param> public EmpNode(AbstractEmployee aemp) : base(aemp.getName()) { emp = aemp; } /// <summary> /// /// </summary> /// <returns></returns> public AbstractEmployee getEmployee() { return emp; } }
窗体调用:
/// <summary> /// 20220918 /// geovindu,Geovin Du,涂聚文 ///Composite Patterns 组合模式 /// </summary> public partial class CompositePatternsForm : Form { AbstractEmployee prez, marketVP, salesMgr; TreeNode rootNode; AbstractEmployee advMgr, emp, prodVP, prodMgr, shipMgr; /// <summary> /// /// </summary> private Random rand; /// <summary> /// /// </summary> private void init() { rand = new Random(); buildEmployeeList(); buildTree(); } /// <summary> /// /// </summary> private void buildEmployeeList() { prez = new Boss(null, "CEO", 200000); marketVP = new Boss(prez, "Marketing VP", 100000); prez.add(marketVP); salesMgr = new Boss(marketVP, "Sales Mgr", 50000); advMgr = new Boss(marketVP, "Advt Mgr", 50000); marketVP.add(salesMgr); marketVP.add(advMgr); prodVP = new Boss(prez, "Production VP", 100000); prez.add(prodVP); advMgr.add("Secy", 20000); //add salesmen reporting to sales manager for (int i = 1; i <= 5; i++) { salesMgr.add("Sales" + i.ToString(), rand_sal(30000)); } prodMgr = new Boss(prodVP, "Prod Mgr", 40000); shipMgr = new Boss(prodVP, "Ship Mgr", 35000); prodVP.add(prodMgr); prodVP.add(shipMgr); for (int i = 1; i <= 3; i++) { shipMgr.add("Ship" + i.ToString(), rand_sal(25000)); } for (int i = 1; i <= 4; i++) { prodMgr.add("Manuf" + i.ToString(), rand_sal(20000)); } } /// <summary> /// /// </summary> private void buildTree() { EmpNode nod; nod = new EmpNode(prez); rootNode = nod; EmpTree.Nodes.Add(nod); addNodes(nod, prez); } /// <summary> /// /// </summary> /// <param name="node"></param> private void getNodeSum(EmpNode node) { AbstractEmployee emp; float sum; emp = node.getEmployee(); sum = emp.getSalaries(); lbSalary.Text = sum.ToString(); } /// <summary> /// /// </summary> /// <param name="nod"></param> /// <param name="emp"></param> private void addNodes(EmpNode nod, AbstractEmployee emp) { AbstractEmployee newEmp; EmpNode newNode; IEnumerator empEnum; empEnum = emp.getSubordinates(); while (empEnum.MoveNext()) { newEmp = (AbstractEmployee)empEnum.Current; newNode = new EmpNode(newEmp); nod.Nodes.Add(newNode); addNodes(newNode, newEmp); } } /// <summary> /// /// </summary> /// <param name="sal"></param> /// <returns></returns> private float rand_sal(float sal) { float rnum = rand.Next(); rnum = rnum / Int32.MaxValue; return rnum * sal / 5 + sal; } /// <summary> /// /// </summary> public CompositePatternsForm() { InitializeComponent(); init(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CompositePatternsForm_Load(object sender, EventArgs e) { } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void EmpTree_AfterSelect(object sender, TreeViewEventArgs e) { EmpNode node; node = (EmpNode)EmpTree.SelectedNode; getNodeSum(node); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btShowBoss_Click(object sender, EventArgs e) { EmpNode node; node = (EmpNode)EmpTree.SelectedNode; AbstractEmployee emp = node.getEmployee(); string bosses = ""; while (emp != null) { bosses += emp.getName() + "\n"; emp = emp.getBoss(); } MessageBox.Show(null, bosses, "Reporting chain"); } }
输出: