设计模式是经验总结,是学习软件设计的有效方法,因此,了解和理解现有的设计模式,是提高软件设计的有效途径之一,这里将介绍相关的设计模式,并通过示例了理解其用法。
迭代器模式(Iterator Pattern)
迭代器模式提供一种顺序访问集合对象中各个元素的方法,而又不暴露其内部的表示(也就是数据结构)。
迭代器模式属于行为型模式。
意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决: 不同的方式来遍历整个整合对象。
何时使用: 遍历一个聚合对象。
如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码: 定义接口:hasNext, next。
应用实例: JAVA 中的 iterator。
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点: 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。
注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
示例
客户希望可以对数据结构中的每个元素进行操作,而不了解数据结构的细节,数据结构根据客户的询问,在生成迭代器的方法中生成一个与数据结构相适应的迭代器,把迭代器交给客户。遍历过程交由迭代器来执行,而不是由数据结构来执行。
这里以雇员列表并遍历为例进行说明。有一个Employee类来表达基本的雇员信息,EmployeeArray类是处理多个雇员信息的集合,现在采用数组来存储数据,提供对外的迭代器,这样,将来改变内部数据结构也没有关系,只需要提供对应的迭代器就可以了。
先来看看迭代器接口,代码如下:
package cn.lut.curiezhang.designpattern.iterator;
public interface IIterator {
public boolean hasNext();
public Employee next();
}
雇员的基本信息,代码如下:
package cn.lut.curiezhang.designpattern.iterator;
public class Employee {
private String firstName;
private String lastName;
private double salary;
private int employeeNumber;
private String department;
public Employee(String firstName, String lastName, double salary, int employeeNumber, String department) {
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
this.employeeNumber = employeeNumber;
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", employeeNumber=" + employeeNumber +
", department='" + department + '\'' +
", salary=" + salary +
'}';
}
}
现在,定义一个雇员迭代器以实现迭代器接口,便于处理雇员列表,代码如下:
package cn.lut.curiezhang.designpattern.iterator;
public class EmployeeIterator implements IIterator {
int size = 0;
int index = 0;
Employee employees[];
public EmployeeIterator(int size, Employee[] employees) {
this.size = size;
this.employees = employees;
}
@Override
public boolean hasNext() {
return index < size;
}
@Override
public Employee next() {
return employees[index++];
}
}
定义一个数据结构接口来获得迭代器,代码如下:
package cn.lut.curiezhang.designpattern.iterator;
public interface IEmployeeData {
public IIterator getIterator();
}
雇员列表数据结构需要提供迭代器实现数据结构接口,代码如下:
package cn.lut.curiezhang.designpattern.iterator;
public class EmployeeArray implements IEmployeeData {
final int max = 10;
Employee[] employees = new Employee[max];
int index = 0;
@Override
public IIterator getIterator() {
return new EmployeeIterator(index, employees);
}
public void add(Employee employee) {
if (index < max - 1) {
employees[index++] = employee;
}
}
}
现在,迭代器模式的框架已经建立,测试代码如下:
package cn.lut.curiezhang.designpattern.iterator;
/**
* Hello world!
*
*/
public class Client
{
private static EmployeeArray employeeArray;
static {
employeeArray = new EmployeeArray();
employeeArray.add(new Employee("Zhang", "san",
3250.0, 1, "MMI研发"));
employeeArray.add(new Employee("Li", "si",
3050.0, 2, "MMI研发"));
employeeArray.add(new Employee("Wang", "wu",
3450.0, 3, "单元测试"));
employeeArray.add(new Employee("Xu", "liu",
3400.0, 4, "单元测试"));
employeeArray.add(new Employee("Zhao", "qi",
3500.0, 5, "单元测试"));
employeeArray.add(new Employee("Zhen", "ba",
3700.0, 6, "需求工程"));
}
public static void main( String[] args )
{
IIterator iterator = employeeArray.getIterator();
while (iterator.hasNext()) {
Employee employee = iterator.next();
System.out.println(employee);
}
}
}
代码执行结果如下图所示:
代码实现就是这样的,下面来看看上面设计模式的基本结构,通过类图了解其基本构成,如下图所示:
了解了其基本结构,就需要搞清楚这些类是怎么样来完成交互的,也就是这些对象之间是如何协作的?就通过顺序图来了解其工作过程,如下图所示:
请注意其交互过程。