技术开发 频道

.NET实用设计模式:组合模式(Composite)

组合模式适用于下面这样的情况:两个或者多个类有相似的形式,或者共同代表某个完整的概念,外界的用户也希望他们合而为一,就可以把这几个类“组合”起来,成为一个新的类,用户只需要调用这个新的类就可以了。

下面举一个例子说明Composite模式的一个实际应用。下面的Class视图:



Employee类是AbstractEmployee接口的一个实现,Boss类是Employee的一个子类,EmpNode是从树视图的TreeNode类继承而来的。我们先看看代码:

AbstractEmployee,这是一个接口,提供下列方法:
public interface AbstractEmployee { float getSalary(); //get current salary string getName(); //get name bool isLeaf(); //true if leaf void add(string nm, float salary); //add subordinate void add(AbstractEmployee emp); //add subordinate IEnumerator getSubordinates(); //get subordinates AbstractEmployee getChild(); //get child float getSalaries(); //get salaries of all }

Employee类是AbstractEmployee接口的一个实现

public class Employee :AbstractEmployee { protected float salary; protected string name; protected ArrayList subordinates;   //------ public Employee(string nm, float salry) { subordinates = new ArrayList(); name = nm; salary = salry; }   //------ public float getSalary() { return salary; }   //------ public string getName() { return name; }   //------ public bool isLeaf() { return subordinates.Count == 0; }   //------ public virtual void add(string nm, float salary) { throw new Exception("No subordinates in base employee class"); }   //------ public virtual void add(AbstractEmployee emp) { throw new Exception("No subordinates in base employee class"); }   //------ public IEnumerator getSubordinates() { return subordinates.GetEnumerator (); }   public virtual AbstractEmployee getChild() { return null; }   //------ 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; } }
从Employee接口和他的一个实现来看,下面很可能要将这个类型的数据组合成一个树的结构。

Boss类是Employee类的派生,他重载了Employee类的add和getChild方法:
public class Boss:Employee { public Boss(string name, float salary):base(name,salary) { } ?? //------ public Boss(AbstractEmployee emp):base(emp.getName() , emp.getSalary()) { } ?? //------ public override void add(string nm, float salary) { AbstractEmployee emp = new Employee(nm,salary); subordinates.Add (emp); } ?? //------ public override void add(AbstractEmployee emp){ subordinates.Add(emp); } ?? //------ 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("New person", 0); } } }

getChild方法是一个递归调用,如果Child不是Leaf,就继续调用下去。上面几个类表达了一个树的结构,表示出了公司中
的领导和雇员的级别关系。

0
相关文章