(声明:本系列所用的模式都来自GOF23中,本系列并不是讲23种经典设计模式,而是如何去使用这些模式)   

 

前面我们设计完成了统计部门工资,这样的一个需求,但是在我们设计遍历员工信息的方法是固定不变的,也就是说是硬编码在PersonComposite类中的,由于Composite设计模式相当于一个树或者图的数据结构,那么他的遍历就会出现变化,比如在遍历部门和小组的时候采取不同的方法,以减少遍历的时间,那么如何去解决这个问题呢?

 

看看我们的意图:我们需要不同的遍历方式,来遍历Composite中的Person列表集合.

 

GOF中的Iterator(遍历器)模式:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。与我们的意图相符,采用!

 

我们来看看代码(具体的代码请查看前一篇,这里只列出关于这一模式的代码):

 

Person:

 

 

 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:

 

 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类型的。

 

客户端代码:

 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();
        }
    }

 

输出结果:

如何使用设计模式来构造系统--(6)

 

OK,这样我们就可以根据自己的需要而去用任何方式遍历PersonComposite,你也可以让PersonComposite维护一个遍历器,然后在初始化PersonComposite时,给与不同的遍历器,方便类库使用人员的调用,具体的看需求了.

 

     下一篇:如何使用设计模式来构造系统--(7)

相关文章: