网站建设销售主管岗位职责,苏州seo排名优化课程,县城做二手车网站,河北住房和城乡建设厅网站首页一、基础概念 迭代器模式的本质是【控制访问聚合对象中的元素】#xff1b; 迭代器模式的功能#xff1a;主要在于提供对聚合对象的迭代访问。迭代器就围绕着这个【访问】做文章#xff0c;延伸出很多功能来#xff0c;如#xff1a; 1、以不同的方式遍历聚合对…一、基础概念 迭代器模式的本质是【控制访问聚合对象中的元素】 迭代器模式的功能主要在于提供对聚合对象的迭代访问。迭代器就围绕着这个【访问】做文章延伸出很多功能来如 1、以不同的方式遍历聚合对象如向前、向后等 2、对同一个聚合同时进行多个遍历 3、以不同的遍历策略来遍历集合如是否需要过滤等 4、多态迭代即为不同的聚合结构提供统一的迭代接口也就是说通过一个迭代接口可以访问不同的聚合结构 注意多态迭代可能会带来类型安全问题可以考虑使用泛型。 迭代器模式的关键思想就是把聚合对象的遍历和访问从聚合对象中分离出来放入单独的迭代器中这样聚合对象会变得简单一些而且迭代器和聚合对象可以独立地变化和发展会加强系统的灵活性。 内部迭代器和外部迭代器 1、内部迭代器指的是由迭代器自己来控制迭代下一个元素的步骤客户端无法干预因此如果想要在迭代的过程中完成工作的话客户端就需要把操作传递给迭代器迭代器在迭代的时候会在每个元素上执行这个操作 2、外部迭代器指的是由客户端来控制迭代下一个元素的步骤 总体来说外部迭代器比内部迭代器要灵活一些因此我们常见的实现也多属于外部迭代器。 带迭代策略的迭代器 1、带迭代策略的迭代器【最典型的就是实现过滤功能的迭代器】即在实际的开发中对于经常被访问的一些数据 可以使用缓存把这些数据存放在内存中。但是不同的业务功能需要访问的数据是不同的还有不同的业务访问权限能访问的数据也是不同的。对于这种情况就可以使用实现过滤功能的迭代器让不同功能使用不同的迭代器来访问。也可以结合策略模式来实现。 2、谁定义遍历算法的问题在迭代器模式中常见的可用来定义遍历算法的地方是【聚合对象本身】【迭代器负责遍历算法】 【聚合对象本身】定义遍历算法的情况下通常会在遍历过程中用迭代器来存储当前迭代的状态这种迭代器被称为游标因为它被用来指示当前的位置。 【迭代器中定义遍历算法】情况下如果实现遍历算法需要访问聚合对象的私有遍历那么将遍历算法放入迭代器中会破坏聚合对象的封装性。 现实开发中具体使用哪一种方式需要根据具体的问题具体分析。 双向迭代器可以同时向前向后遍历数据的迭代器。 迭代器模式的优点 序号迭代器模式的优点1更好的封装性迭代器模式可以让你访问一个聚合对象的内容而无须暴露该聚合对象的内部表示从而提高聚合对象的封装性 《1》可以以不同的遍历方式来遍历一个聚合 《2》 使用迭代器模式使得聚合对象的内容和具体的迭代算法分离开 《3》有了迭代器的接口则聚合本身就不需要再定义这些接口了从而简化了聚合的接口定义2简化客户端调用迭代器为遍历不同的聚合对象提供了一个统一的接口使得客户端遍历聚合对象的内容变得更简单 同一个聚合上可以有多个遍历每个迭代器保持它自己的遍历状态因此可以对同一个聚合对象同时进行多个遍历 何时选用迭代器模式 1、希望提供访问一个聚合对象的内容但是又不想暴露它的内部表示时候可使用迭代器模式来提供迭代器接口从而让客户端只是通过迭代器的接口来访问聚合对象而无须关系聚合对象的内部实现。 2、希望有多种遍历方式可以访问聚合对象 3、希望为遍历不同的聚合对象提供一个统一的接口。
二、迭代器模式示例 业务需求在实际生活中我们会遇到《整合工资表数据》的情况即项目的客户方收购了一家小公司这家小公司有自己的工资系统现在需要整合到客户方已有的工资系统中但是客户方有自己的工资系统且在内部是采用List来记录工资列表而新收购的这家公司的工资系统在内部是采用数组来记录工资列表的幸运的是两个系统用来描述工资的数据模式差不多现在需要整合者两个工资系统的工资数据【最简单的方法就是直接把信收购的这家公司的工资系统也修改为内部使用List来记录工资列表但是经过仔细查看源代码发现有很多代码跟这个数组有关还有很多重要的逻辑处理只好搁置】现在除了需要把两个工资系统整合起来外老板还希望能够通过决策辅助系统来统一查看工资数据不想看到两份不同的工资表那么该如何实现 2.1、不使用迭代器模式的示例
1、定义工资描述模型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern
{/// summary/// 工资描述模型对象/// /summaryinternal class PayModel{/// summary/// 支付工资的人员/// /summarypublic string? UserName { get; set; }/// summary/// 支付的工资数额/// /summarypublic double Pay { get; set; }public override string ToString(){string str $用户【{UserName}】的工资是【{Pay}】;return str;}}//Class_end
}2、客户方已有的List工资管理类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern
{/// summary/// 客户方已有的工资管理对象/// /summaryinternal class PayManager{//聚合对象private ListPayModel payModels new ListPayModel();/// summary/// 获取工资列表/// /summary/// returns/returnspublic ListPayModel GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 张三;payModel1.Pay 9600;payModels.Add(payModel1);PayModel payModel2 new PayModel();payModel2.UserName 李四;payModel2.Pay 10000;payModels.Add(payModel2);PayModel payModel3 new PayModel();payModel3.UserName 王五;payModel3.Pay 12000;payModels.Add(payModel3);}}//Class_end
}3、客户方收购的那家使用数组管理的工资管理类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern
{/// summary/// 被客户方收购公司的工资管理类/// /summaryinternal class SalaryManager{//用数组管理private PayModel[] payModelsnew PayModel[3];/// summary/// 获取工资列表/// /summary/// returns/returnspublic PayModel[] GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 赵六;payModel1.Pay 9000;payModels[0]payModel1;PayModel payModel2 new PayModel();payModel2.UserName 孙七;payModel2.Pay 13000;payModels[1] payModel2;PayModel payModel3 new PayModel();payModel3.UserName 李八;payModel3.Pay 15000;payModels[2] payModel3;}}//Class_end
}4、客户端访问这两个工资列表需要采用不同的访问方式一个是List一个是数组
namespace IteratorPattern
{internal class Program{static void Main(string[] args){GetPaySalaryTest();Console.ReadLine();}/// summary/// 获取到支付薪水的测试/// /summaryprivate static void GetPaySalaryTest(){Console.WriteLine(---获取到支付薪水的测试---);//访问集团的工资列表PayManager payManager new PayManager();//先计算在获取payManager.CaculatePay();ListPayModel payModelList payManager.GetPayModels();Console.WriteLine(---集团的工资列表信息);foreach (var payModel in payModelList){Console.WriteLine(payModel);}//访问新收购公司的工资列表SalaryManager salaryManager new SalaryManager();salaryManager.CaculatePay();PayModel[] payModelsArray salaryManager.GetPayModels();Console.WriteLine(---新收购公司的工资信息);foreach (var payModel in payModelsArray){Console.WriteLine(payModel);}}}//Class_end
}5、运行结果 2.2、使用迭代器模式的示例 仔细分析我们的业务需求后发现其实就是要求以一个统一的方式来访问内部实现不同的聚合对象首先需要把这个统一的访问方式定义出来接口方法迭代器迭代的是具体的聚合对象那么不同的聚合对象就应该有不同的迭代器为了让迭代器以一个统一的方式来操作聚合对象因此给所有的聚合对象抽象一个公共的父类让它来操作聚合对象的公共接口。
1、定义接口和方法可让客户端以统一的方式进行访问
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 迭代器接口定义访问和遍历元素的操作/// /summaryinternal interface Itetator{/// summary/// 移动到聚合对象的第一个位置/// /summaryvoid First();/// summary/// 移动到聚合对象的下一个位置/// /summaryvoid Next();/// summary/// 判断是否已经移动到聚合对象的最后一个位置/// /summary/// returnstrue:表示已经移动到聚合对象的最后一个位置/returnsbool IsDone();/// summary/// 获取迭代的当前元素/// /summary/// returns/returnsobject CurrentItem();}//Interface_end
}2、分别定义List与数组类继承迭代接口实现 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 用来实现访问数组的迭代接口/// /summaryinternal class ArrayIteratorImpl : Itetator{//用来存放被迭代的聚合对象private SalaryManager salaryManager null;//用来记录当前迭代的位置索引-1表示刚开始时迭代器指向聚合对象第一个对象之前private int index -1;/// summary/// 构造函数/// /summary/// param namesalaryManager被客户方收购公司的工资管理类/parampublic ArrayIteratorImpl(SalaryManager salaryManager){this.salaryManager salaryManager;}public object CurrentItem(){return this.salaryManager.Get(index);}public void First(){index 0;}public bool IsDone(){if (indexthis.salaryManager.Size()){return true;}return false;}public void Next(){if (indexsalaryManager.Size()){indexindex1;}}}//Class_end
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 用来实现访问Collection集合的迭代接口为了外部统一访问/// /summaryinternal class CollectionIteratorImpl : Itetator{//用来存放被迭代的聚合对象private PayManager payManagernull;//用来记录当前迭代的位置索引-1表示刚开始时迭代器指向聚合对象第一个对象之前private int index-1;/// summary/// 构造函数/// /summary/// param namepayManager客户方已有的工资管理对象/parampublic CollectionIteratorImpl(PayManager payManager){this.payManager payManager;}public object CurrentItem(){return this.payManager.Get(index);}public void First(){index 0;}public bool IsDone(){if (index this.payManager.Size()){return true;}return false;}public void Next(){if (indexthis.payManager.Size()){index index 1;}}}//Class_end
}3、获取访问聚合的接口 我们现在已经定义好了统一访问聚合的接口也分别实现了接口方法现在在客户端需要如何才能获取这个访问聚合的接口呢且需要以统一的方式来获取【一个简单的方案就是定义一个聚合的接口的接口即客户端先通过这个接口来获取访问聚合的接口然后在访问聚合对象】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 聚合对象定义创建相应迭代器对象的接口/// /summaryinternal abstract class Aggregate{//工厂方法场景相应迭代器对象的接口public abstract Itetator CreateIterator();//获取对象public abstract object Get(int index);//获取对象大小public abstract int Size();}//Class_end
}4、分别让具体的聚合对象继承抽象来分别提供访问它们的聚合接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 客户方已有的工资管理对象/// /summaryinternal class PayManager:Aggregate{//聚合对象private ListPayModel payModels new ListPayModel();/// summary/// 获取工资列表/// /summary/// returns/returnspublic ListPayModel GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 张三;payModel1.Pay 9600;payModels.Add(payModel1);PayModel payModel2 new PayModel();payModel2.UserName 李四;payModel2.Pay 10000;payModels.Add(payModel2);PayModel payModel3 new PayModel();payModel3.UserName 王五;payModel3.Pay 12000;payModels.Add(payModel3);}public override Itetator CreateIterator(){return new CollectionIteratorImpl(this);}public override object Get(int index){object obj null;if (indexpayModels.Count){obj payModels[index];}return obj;}public override int Size(){return this.payModels.Count;}}//Class_end
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 被客户方收购公司的工资管理类/// /summaryinternal class SalaryManager:Aggregate{//用数组管理private PayModel[] payModelsnew PayModel[3];/// summary/// 获取工资列表/// /summary/// returns/returnspublic PayModel[] GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 赵六;payModel1.Pay 9000;payModels[0]payModel1;PayModel payModel2 new PayModel();payModel2.UserName 孙七;payModel2.Pay 13000;payModels[1] payModel2;PayModel payModel3 new PayModel();payModel3.UserName 李八;payModel3.Pay 15000;payModels[2] payModel3;}public override Itetator CreateIterator(){return new ArrayIteratorImpl(this);}public override object Get(int index){object obj null;if (indexpayModels.Length){obj payModels[index];}return obj;}public override int Size(){return this.payModels.Length;}}//Class_end
}5、实现统一的客户端访问
namespace IteratorPattern
{internal class Program{static void Main(string[] args){GetPaySalaryAggregateTest();Console.ReadLine();}/// summary/// 获取到支付薪水的聚合测试/// /summaryprivate static void GetPaySalaryAggregateTest(){Console.WriteLine(---获取到支付薪水的聚合测试---);//访问集团的工资列表AggregateOne.PayManager payManager new AggregateOne.PayManager();//先计算再获取payManager.CaculatePay();Console.WriteLine(---集团的工资列表信息);Print(payManager.CreateIterator());//访问新收购公司的工资列表AggregateOne.SalaryManager salaryManager new AggregateOne.SalaryManager();salaryManager.CaculatePay();Console.WriteLine(---新收购公司的工资信息);Print(salaryManager.CreateIterator());}private static void Print(AggregateOne.Itetator it){//循环输出聚合对象中的值//首先设置迭代器到第一个元素it.First();while (!it.IsDone()){//取出当前的元素object obj it.CurrentItem();Console.WriteLine($当前对象是【{obj}】);//如果没有迭代到最后则继续向下迭代it.Next();}}}//Class_end
}迭代器的过滤示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.AggregateOne
{/// summary/// 用来实现访问Collection集合的迭代接口为了外部统一访问/// /summaryinternal class CollectionIteratorImplFilter : Itetator{//用来存放被迭代的列表private ListPayModel payModelsnull;//用来记录当前迭代的位置索引private int index0;/// summary/// 构造函数/// /summary/// param namepayManager客户方已有的工资管理对象/parampublic CollectionIteratorImplFilter(PayManager payManager){/*迭代器过滤示意*///可以先在这里对聚合对象的数据进行过滤比如工资必须在10000以下ListPayModel tmpPayModels new ListPayModel();foreach (var item in payManager.GetPayModels()){if (item.Pay 10000){tmpPayModels.Add(item);}}//然后把符合要求的数据存放到迭代的列表this.payModels tmpPayModels;foreach (var item in tmpPayModels){payModels.Add(item);}}public object CurrentItem(){return this.payModels[index];}public void First(){index 0;}public bool IsDone(){if (index this.payModels.Count){return true;}return false;}public void Next(){if (indexthis.payModels.Count){index index 1;}}}//Class_end
}2.3、翻页迭代——内存顺序翻页 在实际的软件开发中我们经常用到翻页功能但翻页功能也有几种实现方法
《1》纯数据库实现依靠SQL提供的功能实现翻页用户每次请求翻页就会从数据库中获取相应的数据【这是典型的时间换空间策略】。
《2》纯内存实现就是一次性从数据库中把需要的所有数据都取出来放到内存中然后用户请求翻页时从内存中获取相应的数据【这是典型的空间换时间策略】。 在实际的开发中小型系统一般采用第一种方案因为内存实在太宝贵了中大型的系统一般是把两个方案结合起来综合利用它们的优点而又规避它们的缺点从而实现更好的翻页功能。
《3》纯数据库纯内存实现思路是如果每页显示10条记录根据判断用户很少翻到10页以后那好第一次访问的时候就一次性从数据库中获取前10页的数据100条记录都存放在内存里面这样一来只要当用户在前10页内进行翻页操作时就不用再访问数据库了而是直接从内存获取速度就快了。当用户想获取第11页的数据此时就再次访问数据库那么此时获取多少页数据合适呢最简单的方法就是继续获取10页的数据而一种较好的方式是根据访问统计进行衰减访问如折半获取【即第一次获取10页第二次就获取5页第三次获取3页第四次获取2页第五次获取1页】。
1、创建翻页迭代器接口
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.PageTurning
{/// summary/// 定义翻页访问聚合元素的迭代接口/// /summaryinternal interface IAggregateIterator{/// summary/// 判断是否还有下一个元素无论是否足够一页的数据因为最后哪怕只有一条数据也算一页/// /summary/// returns若有下一个元素则返回true否则就返回false/returnsbool hasNext();/// summary/// 取出后面的几个元素/// /summary/// param nametotalNum需取出的记录条数/param/// returns/returnsListobject Next(int totalNum);/// summary/// 判断是否有上一个元素无论是否够一页的数据因为最后哪怕只有一条数据也要算一页/// /summary/// returns若有上一个元素则返回true否则返回false/returnsbool hasPrevious();/// summary/// 取出前面的几个元素/// /summary/// param nametotalNum需获取的记录条数/param/// returns/returnsListobject Previous(int totalNum);}//Interface_end
}2、工资模型保持不变
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.PageTurning
{/// summary/// 定义翻页访问聚合元素的迭代接口/// /summaryinternal interface IAggregateIterator{/// summary/// 判断是否还有下一个元素无论是否足够一页的数据因为最后哪怕只有一条数据也算一页/// /summary/// returns若有下一个元素则返回true否则就返回false/returnsbool hasNext();/// summary/// 取出后面的几个元素/// /summary/// param nametotalNum需取出的记录条数/param/// returns/returnsListobject Next(int totalNum);/// summary/// 判断是否有上一个元素无论是否够一页的数据因为最后哪怕只有一条数据也要算一页/// /summary/// returns若有上一个元素则返回true否则返回false/returnsbool hasPrevious();/// summary/// 取出前面的几个元素/// /summary/// param nametotalNum需获取的记录条数/param/// returns/returnsListobject Previous(int totalNum);}//Interface_end
}3、薪资管理类实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.PageTurning
{/// summary/// 被客户方收购公司的工资管理类/// /summaryinternal class SalaryManager{//用数组管理private PayModel[] payModelsnew PayModel[5];/// summary/// 获取工资列表/// /summary/// returns/returnspublic PayModel[] GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 赵六;payModel1.Pay 9000;payModels[0]payModel1;PayModel payModel2 new PayModel();payModel2.UserName 孙七;payModel2.Pay 13000;payModels[1] payModel2;PayModel payModel3 new PayModel();payModel3.UserName 李八;payModel3.Pay 15000;payModels[2] payModel3;PayModel payModel4 new PayModel();payModel4.UserName 孙七二;payModel4.Pay 9000;payModels[3] payModel4;PayModel payModel5 new PayModel();payModel5.UserName 李七二;payModel5.Pay 9000;payModels[4] payModel5;}public IAggregateIterator CreateIterator(){return new ArrayIteratorImpl(this); }}//Class_end
}4、创建继承迭代器接口类实现具体的方法
using IteratorPattern.AggregateOne;
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.PageTurning
{/// summary/// 用来实现访问数组的迭代接口/// /summaryinternal class ArrayIteratorImpl : IAggregateIterator{//用来存放被迭代的数组private PayModel[] payModels null;//用来记录当前迭代的位置索引private int index 0;/// summary/// 构造函数/// /summary/// param namesalaryManager被客户方收购公司的工资管理类/parampublic ArrayIteratorImpl(SalaryManager salaryManager){this.payModels salaryManager.GetPayModels();}public bool hasNext(){if (payModels!null index(payModels.Length-1)){return true;}return false;}public bool hasPrevious(){if (payModels!null index0){return true;}return false;}public Listobject Next(int totalNum){Listobject list new Listobject();int count 0;while (hasNext() counttotalNum){list.Add(payModels[index]);//每取走一个值索引就添加1index;count;}return list;}public Listobject Previous(int totalNum){Listobject list new Listobject();int count 0;//简单的实现就是把索引退回去totalNum个然后在取值但事实上这种实现是有可能多退回数据的//比如已经到了最后一页而且最后一页的数据不够一页的数据那么退回totalNum个索引就退多了//为了示例的简洁性我们就不去处理了index index - totalNum;while (hasPrevious() counttotalNum){list.Add(payModels[index]);index;count;}return list;}}//Class_end
}5、客户端测试翻页
namespace IteratorPattern
{internal class Program{static void Main(string[] args){PageTurningTest();Console.ReadLine();}/// summary/// 测试翻页/// /summaryprivate static void PageTurningTest(){Console.WriteLine(---测试翻页---);//访问新收购公司的工资列表PageTurning.SalaryManager salaryManager new PageTurning.SalaryManager();salaryManager.CaculatePay();//得到翻页迭代器PageTurning.IAggregateIterator irsalaryManager.CreateIterator();//获取第一页每页显示2条Listobject list ir.Next(2);Console.WriteLine($第一页数据);Print2(list);//获取第二页每页显示2条Listobject list2 ir.Next(2);Console.WriteLine($第二页数据);Print2(list2);//向前翻一页即再次获取第二页Listobject list3 ir.Previous(2);Console.WriteLine($再次获取第二页数据);Print2(list3);}private static void Print2(Listobject list){foreach (var item in list){Console.WriteLine(item);}}}//Class_end
}6、运行结果 2.4、翻页迭代——随机翻页
1、定义迭代接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.RandomPageTurning
{/// summary/// 定义随机翻页访问聚合元素的迭代接口/// /summaryinternal interface IAggregationIteratorT where T : class{/// summary/// 判断是否还有下一个元素无所谓是否够一页的数据因为最后哪怕只有一条数据也是算作一页/// /summary/// returns如果有下一个元素则返回true,否则返回false/returnspublic bool HasNext();/// summary/// 判断是否还有上一个元素无所谓是否够一页的数据因为最后哪怕只有一条数据也是算作一页/// /summary/// returns如果有上一个元素则返回true,否则返回false/returnspublic bool HasPrevious();/// summary/// 取指定页的数据/// /summary/// param namepageNum需获取数据的页码/param/// param namepageShow每页展示的数据条数/param/// returns/returnspublic T[] GetPageDatas(int pageNum,int pageShow);}//Interface_end
}2、定义具体的类继承该接口并实现方法内容
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.RandomPageTurning
{internal class ArrayIteratorImpl : IAggregationIteratorPayModel{//用来存放被迭代的数组private PayModel[] payModels null;//用来记录当前迭代到的索引位置private int index 0;/// summary/// 构造函数/// /summary/// param namesalaryManager薪资管理对象/parampublic ArrayIteratorImpl(SalaryManager salaryManager){this.payModels salaryManager.GetPayModels();}public PayModel[] GetPageDatas(int pageNum, int pageShow){PayModel[] payModelArray new PayModel[pageShow];//需要先计算需获取的数据开始条数和结束条数int start (pageNum - 1) * pageShow;int end start pageShow - 1;//控制start的边界最小是0if (start0){start 0;}//控制end的边界最大是数组的最大索引if (endthis.payModels.Length-1){end this.payModels.Length - 1;}//每次取值都是从头开始循环所以设置index0index 0;while (HasNext() startend){payModelArray[index] payModels[start];start;index;}return payModelArray;}public bool HasNext(){if (payModels!null indexpayModels.Length-1){return true;}return false;}public bool HasPrevious(){if (payModels!null index0){return true;}return false;}}//Class_end
}3、给客户收购公司的薪水管理类新增该迭代接口的实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace IteratorPattern.RandomPageTurning
{/// summary/// 被客户方收购公司的工资管理类/// /summaryinternal class SalaryManager{//用数组管理private PayModel[] payModelsnew PayModel[5];/// summary/// 获取工资列表/// /summary/// returns/returnspublic PayModel[] GetPayModels(){return payModels;}/// summary/// 计算工资(正常来说应该有很多参数我们只是演示就从简了)/// /summarypublic void CaculatePay(){//计算工资把工资信息填充到工资条中//为了测试需要一些测试数据PayModel payModel1 new PayModel();payModel1.UserName 赵六;payModel1.Pay 9000;payModels[0] payModel1;PayModel payModel2 new PayModel();payModel2.UserName 孙七;payModel2.Pay 13000;payModels[1] payModel2;PayModel payModel3 new PayModel();payModel3.UserName 李八;payModel3.Pay 15000;payModels[2] payModel3;PayModel payModel4 new PayModel();payModel4.UserName 孙七二;payModel4.Pay 9000;payModels[3] payModel4;PayModel payModel5 new PayModel();payModel5.UserName 李七二;payModel5.Pay 9000;payModels[4] payModel5;}public IAggregationIteratorPayModel CreateIterator(){return new ArrayIteratorImpl(this);}}//Class_end
}4、客户端测试随机翻页
namespace IteratorPattern
{internal class Program{static void Main(string[] args){RandomPageTurningTest();Console.ReadLine();}/// summary/// 测试随机翻页/// /summaryprivate static void RandomPageTurningTest(){Console.WriteLine(---测试随机翻页---);//访问新收购公司的工资列表RandomPageTurning.SalaryManager salaryManager new RandomPageTurning.SalaryManager();//先计算工资数据salaryManager.CaculatePay();//得到翻页迭代器RandomPageTurning.IAggregationIteratorRandomPageTurning.PayModel it (RandomPageTurning.IAggregationIteratorRandomPageTurning.PayModel)salaryManager.CreateIterator();//获取第一页数据每页显示2条RandomPageTurning.PayModel[] payModelArray1 it.GetPageDatas(1,2);Console.WriteLine($第一页的数据是:);Print3(payModelArray1);//获取第二页数据每页显示2条RandomPageTurning.PayModel[] payModelArray2 it.GetPageDatas(2, 2);Console.WriteLine($第二页的数据是:);Print3(payModelArray2);//获取第一页数据每页显示2条RandomPageTurning.PayModel[] payModelArray3 it.GetPageDatas(1, 2);Console.WriteLine($第一页的数据是:);Print3(payModelArray3);//获取第三页数据每页显示2条RandomPageTurning.PayModel[] payModelArray4 it.GetPageDatas(3, 2);Console.WriteLine($第三页的数据是:);Print3(payModelArray4);}private static void Print3(RandomPageTurning.PayModel[] payModelArray){foreach (var item in payModelArray){Console.WriteLine(item);}}}//Class_end
}6、测试结果 三、项目源码工程
kafeiweimei/Learning_DesignPattern: 这是一个关于C#语言编写的基础设计模式项目工程方便学习理解常见的26种设计模式https://github.com/kafeiweimei/Learning_DesignPattern