前面我们设计完成了统计部门工资,这样的一个需求,但是在我们设计遍历员工信息的方法是固定不变的,也就是说是硬编码在PersonComposite类中的,由于Composite设计模式相当于一个树或者图的数据结构,那么他的遍历就会出现变化,比如在遍历部门和小组的时候采取不同的方法,以减少遍历的时间,那么如何去解决这个问题呢?
(声明:本系列所用的模式都来自GOF23中,本系列并不是讲23种经典设计模式,而是如何去使用这些模式)
前面我们设计完成了统计部门工资,这样的一个需求,但是在我们设计遍历员工信息的方法是固定不变的,也就是说是硬编码在PersonComposite类中的,由于Composite设计模式相当于一个树或者图的数据结构,那么他的遍历就会出现变化,比如在遍历部门和小组的时候采取不同的方法,以减少遍历的时间,那么如何去解决这个问题呢?
看看我们的意图:我们需要不同的遍历方式,来遍历Composite中的Person列表集合.
GOF中的Iterator(遍历器)模式:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。与我们的意图相符,采用!
我们来看看代码(具体的代码请查看前一篇,这里只列出关于这一模式的代码):
Person:
Code
public interface IComposite
{
double GetShouldpaid();
}
public class PersonComposite :IComposite
{
private ArrayList composite=new ArrayList(); //维护一个Icomposite的列表
public ArrayList Composite
{
get{return composite;}
set { composite = value; }
}
public void AddComposite(IComposite com)
{
composite.Add(com); //添加一个Icomposite的子类
}
public void RemoveComposite(IComposite com)
{
composite.Remove(com); //删除一个Icomposite 的子类
}
public double GetShouldpaid()
{
double x=0;
for (int i = 0; i < composite.Count; i++) //遍历当前维护的Icomposite的列表
{
IComposite com = (IComposite)composite[i];
x += com.GetShouldpaid(); //递归到当前列表i元素的GetShouldpaid
}
return x;
}
}
Iterator:
Code
public interface Iterator
{
IComposite First(); //数据结构的第一个元素
bool Next(); //当前的下一个元素
IComposite Current(); //当前元素
}
public class Listterator : Iterator //具体的Iterator
{
private int i=-1; //标记当前位置
public PersonComposite com; //维护一个数据结构
public Listterator(PersonComposite agg)
{
this.com = (PersonComposite)agg;
}
public IComposite First()
{
return (IComposite)com.Composite[0];
}
public bool Next()
{
i++;
if (i>com.Composite.Count-1)
{
i = com.Composite.Count-1;
return false;
}
return true;
}
public IComposite Current()
{
return (IComposite)com.Composite[i];
}
}
在遍历器中维护了一个PersonComposite,这样的数据结构,你可以自己定义任何的数据结构,让Iterator来维护和遍历,这里没有用到Person这个叶结点,是因为他没有列表不需要去遍历,而PersonComposite的列表中,既可能有Person,也可能有PersonComposite他们都继承自Icomposite,所以Iterator的接口中的方法,都是返回Icomposite类型的。
客户端代码:
Code
class Program
{
static void Main(string[] args)
{
StaffAndSalaryFactory saf = new StaffAndSalaryFactory(); //实例化工厂
AbstractPerson staff1 = saf.GetPerson(); //创建员工
staff1.PersonName = "涵舍愚人1";
staff1.PersonSalary = saf.GetSalary();//创建员工工资
staff1.PersonSalary.Salaryprize = BadPrize.badPrize;//使用单件初始化员工工资的绩效部分
//该员工工资为:6000+绩效3000=9000
AbstractPerson staff2 = saf.GetPerson(); //创建员工
staff2.PersonName = "涵舍愚人2";
staff2.PersonSalary = saf.GetSalary();//创建员工工资
staff2.PersonSalary.Salaryprize = GoodPrize.goodPrize;//使用单件初始化员工工资的绩效部分
//该员工工资为:6000+绩效6000=12000
PersonComposite pc2 = new PersonComposite();
pc2.AddComposite(staff2);//将Staff2加到部门PC2
pc2.AddComposite(staff1);//将Staff2加到部门PC2
Listterator ltt = new Listterator(pc2); //初始化遍历器
while (ltt.Next())
{
AbstractPerson com= ltt.Current() as AbstractPerson;
if (com != null) //如果是具体人员则打印出他的工资
{
Console.Write(com.PersonName+"\t"+ com.GetShouldpaid() + "\r\n");
}
}
Console.Read();
}
}
输出结果:
OK,这样我们就可以根据自己的需要而去用任何方式遍历PersonComposite,你也可以让PersonComposite维护一个遍历器,然后在初始化PersonComposite时,给与不同的遍历器,方便类库使用人员的调用,具体的看需求了.
下一篇:如何使用设计模式来构造系统--(7)