摘要:本文用一个实例场景描述Gof 23设计模式中的迭代子(Iterator)模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 迭代子模式 Quarkus
1 基础知识
1.1 标准定义
迭代子(Iterator)模式标准定义:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
1.2 分析和说明
迭代子(Iterator)模式称迭代器模式,属于对象行为型模式。迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
迭代子(Iterator)模式结构如图1所示,其角色包括抽象迭代子(Iterator)角色、具体迭代子(Concrete Iterator)角色、聚集(Aggregate)角色、具体聚集(Concrete Aggregate)角色和客户端(Client)角色。
图1 迭代子模式结构
抽象迭代子(Iterator)角色:此抽象角色定义出遍历元素所需的接口。
具体迭代子(Concrete Iterator)角色:此角色实现了Iterator接口,并保持迭代过程中的游标位置。
聚集(Aggregate)角色:此抽象角色给出创建迭代子(Iterator)对象的接口。
具体聚集(Concrete Aggregate)角色:实现了创建迭代子(Iterator)对象的接口,返回一个合适的具体迭代子实例。
客户端(Client)角色:持有对聚集及其迭代子对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除。
2 应用场景举例
比如公司想统计一下所有员工中有硕士文凭的人数和他们的姓名。可以把所有员工都放到一个集合中,然后一个一个地询问是否是硕士,这样就可以获得有多少个硕士了。用例图见图2。
图2 迭代子模式用例图
在这里可以把Iterator抽象类理解为抽象迭代子(Iterator)角色。ImplementIterator类是具体迭代子(Concrete Iterator)角色。EmployeeCollection类是具体聚集(Concrete Aggregate)角色。其实现类图如图3所示。ImplementIterator类实现Iterator接口并关联EmployeeCollection。Employee类聚合EmployeeCollection类,即EmployeeCollection包容多个Employee。
图3 迭代子模式结构类图
迭代子模式实现顺序图见图4,实现顺序描述:① 基于Employee类创建employee对象;② 基于EmployeeCollection类创建employeeCollection对象;③ 把employee对象添加到employeeCollection对象;④ 基于ImplementIterator类创建iterator对象;⑤ 调用iterator对象的next方法,对employeeCollection对象进行循环访问。
图4 迭代子模式实现顺序图
3.Quarkus的实现程序代码
Quarkus程序实现主要包括Iterator抽象类文件,ImplementIterator类文件,EmployeeCollection类文件和Employee类文件等4个文件。其关系如图3所示。下面分别列出这4个文件的程序代码,最后列出测试代码并显示输出结果。
Iterator抽象类程序代码清单01所示。
程序代码清单01
public abstract class Iterator {
public Employee next(){return null;};
public Employee previous(){return null;};
}
ImplementIterator类继承Iterator抽象类,其程序代码清单02所示。
程序代码清单02
@ApplicationScoped
public class ImplementIterator extends Iterator {
private EmployeeCollection employeeCollection;
private int currentIndex;
public ImplementIterator (){}
public ImplementIterator (EmployeeCollection collection){
initizeIterator(collection);
}
private void initizeIterator(EmployeeCollection collection) {
employeeCollection = collection;
currentIndex = collection.getEmployeeMax() - 1;
}
public void setEmployeeCollection(EmployeeCollection collection) {
employeeCollection = collection;
currentIndex = collection.getEmployeeMax() - 1;
}
public Employee next() {
if (currentIndex == -1) return null;
return employeeCollection.getEmployee(currentIndex--);
}
}
EmployeeCollection类程序代码清单03所示。
程序代码清单03
@ApplicationScoped
public class EmployeeCollection {
List<Employee> employeeList = new ArrayList<Employee>();
private int employeeMax = 0;
public EmployeeCollection(){}
public EmployeeCollection addEmployee(Employee employee) {
employeeList.add(employee);
employeeMax++;
return this ;
}
public Employee getEmployee(int i) {
return ((Employee) employeeList.get(i));
}
public int getEmployeeMax() {
return employeeMax;
}
public void setEmployeeMax(int employeeMax) {
this.employeeMax = employeeMax;
}
}
Employee类程序代码清单04所示。
程序代码清单04
@Dependent
public class Employee {
private String employeeName;
private String education ;
public Employee(){ }
public Employee(String name ,String ed ){
this.employeeName = name;
this.education = ed;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEducation() {
return education;
}
public void setEducation(String education) {
this.education = education;
}
}
迭代子模式测试程序的代码清单05如下:
程序代码清单05
public class IteratorClient implements QuarkusApplication{
@ConfigProperty(name = "gof23.behavioralpattern.iterator.title", defaultValue = "gof23")
String title;
@Inject Employee employee1,employee2,employee3,employee4,employee5;
@Inject EmployeeCollection employeeCollection;
@Inject ImplementIterator iterator;
@Override
public int run(String... args){
System.out.println("————————" + title + "演示输出—————————");
Employee employee;
employee1.setEmployeeName("小王");
employee1.setEducation("学士");
employee2.setEmployeeName("小张");
employee2.setEducation("学士");
employee3.setEmployeeName("小刘");
employee3.setEducation("硕士");
employee4.setEmployeeName("小李");
employee4.setEducation("学士");
employee5.setEmployeeName("小马");
employee5.setEducation("硕士");
employeeCollection.addEmployee(employee1).addEmployee(employee2);
employeeCollection.addEmployee(employee3).addEmployee(employee4);
employeeCollection.addEmployee(employee5);
iterator.setEmployeeCollection(employeeCollection);
do {
employee = iterator.next();
if (employee != null) {
if (employee.getEducation().equals("硕士")){
System.out.println(employee.getEmployeeName()+";");
}
}
} while (employee != null);
return 0;
}
public static void main(String... args) {
Quarkus.run(IteratorClient.class, args);
}
}
迭代子模式测试类输出结果如下所示:
小马;小刘;
4. 相关Quarkus程序源码下载
可以直接从github上获取代码,读者可以从github上clone预先准备好的示例代码。
git clone https://github.com/rengang66/quarkus-sample-gof23.git
这是一个Maven项目,然后Maven导入工程。该程序位于“src\main\java\com\iiit\quarkus\sample\gof23\behavioralpattern\iterator”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
5 扩展和说明
在JDK中,已经实现了lterator模式。在JDK中的java.util.Iterator就是针对jave.util.Collection的lterator模式实现。Collection接口下的子接口包括Set、Array、List等。
参考文献
[1] E.Gamma, R.Helm, R.Johnson, and Vlissides. Design Patterns Elements of Reusable Object Oriented Software. Addison-Wesley, 1995
[2] E.Gamma, R.Helm, R.Johnson, and Vlissides.著,李英军等译,设计模式:可复用面向对象软件的基础,北京:机械工业出版社.2000.9.
[3] 阎宏,Java与模式,北京:电子工业出版社. 2002.10
[4] 王俊峰 戚晓滨. 设计模式和UML. 计算机应用研究,1999.16(5), 27-29,39.
[5] 陈琴 朱正强. UML在设计模式描述中的应用. 计算机工程与设计,2003.24(4), 81-84.
[6] 板桥里人. Jive和设计模式. 程序员,2003.(6), 58-60.
[7] 谭炎 潘久辉. 开放源代码项目Jive的体系结构与设计模式. 科学技术与工程,2005.5(15), 1087-1090.
[8] 王长斌. 软件设计模式及其在Java类库中的典型实现. 鞍山师范学院学报,2004.6(4), 52-55.
[9] 郭庆林. Iterator模式产生原因和实例分析. 中国科教创新导刊,2008.(4), 66-67.
[10] 聂颖. 设计模式在图形处理软件中的应用. 计算机应用,2004.24(B12), 189-191.
[11] Rob Pierry. 揭露.NET框架中使用的设计模式. MSDN开发精选,2005.(4), 95-100.
[12] 何江玲 孙其博. 设计模式在软交换软件系统中的应用. 世界电信,2003.16(9), 42-44.
[13] 叶建平. 设计模式在游乐设施检测管理信息系统中的应用. 微计算机信息,2005.21(12X), 213-214,77.
[14] Quarkus官网. https://quarkus.io/