迭代器模式
1.定義:
提供一種方法順序訪問一個容器對象中的各個元素葫盼,而又不需要暴露該對象的內部表示闲先。
2.使用場景:
- 遍歷一個容器對象時。
3.UML圖
4.詳解:
迭代器模式(Iterator Pattern)又稱游標模式(Cursor Pattern),是一種行為型設計模式。迭代器模式是一種比較常用的設計模式殊轴,其源于對容器的訪問钦奋,如訪問Java中的List座云,Map,Array中的元素等付材,必然會涉及遍歷算法朦拖,這個時候,我們可以將遍歷方法封裝在容器內或不提供遍歷方法厌衔。如果封裝遍歷方法在容器中璧帝,對于容器類來講過,則承擔了過多的功能富寿,容器類不僅要維護自身內部的數(shù)據(jù)元素而且還要對外提供遍歷接口方法睬隶,因為遍歷狀態(tài)的存儲問題還不能對同一個容器同時進行多個遍歷操作;如果不提供遍歷方法作喘,則需要使用者自己實現(xiàn)理疙,這樣就暴露了容器的內部細節(jié),因此泞坦,迭代器模式是最佳選擇窖贤。在客戶訪問類與容器類之間插入一個第三者——迭代器,可以完美解決上述問題。
下面就以Min和Hui兩人統(tǒng)計在職人員信息(包括name,age,sex,job)舉例赃梧,詳見代碼:
public static class Employee {
private String name;//姓名
private int age;//年齡
private String sex;//性別
private String job;//職務
public Employee(String name, int age, String sex, String job) {
this.name = name;
this.age = age;
this.sex = sex;
this.job = job;
}
@Override
public String toString() {
return "Emplyee{name=" + name + ",age=" + age + ",sex=" + sex + ",job=" + job + "}";
}
}
然后分別是Min和Hui的統(tǒng)計方法滤蝠,Min把統(tǒng)計信息存于List中,Hui把統(tǒng)計信息存于Array中:
public static class Min {
private List<Employee> list = new ArrayList<>();
private Employee lilei = new Employee("lilei", 18, "male", "job1");
private Employee hanmeimei = new Employee("hanmeimei", 28, "female", "job2");
private Employee lily = new Employee("lily", 24, "female", "job0");
private Employee tantong = new Employee("tantong", 42, "male", "job0");
public Min() {
list.add(lilei);
list.add(hanmeimei);
list.add(lily);
list.add(tantong);
}
public List<Employee> getList() {
return list;
}
}
public static class Hui {
private Employee[] array = new Employee[4];
private Employee green = new Employee("green", 39, "male", "job0");
private Employee lucy = new Employee("lucy", 20, "female", "job1");
private Employee lancy = new Employee("lancy", 16, "female", "job2");
private Employee jacky = new Employee("jacky", 35, "male", "job1");
public Hui() {
array[0] = green;
array[1] = lucy;
array[2] = lancy;
array[3] = jacky;
}
public Employee[] getArray() {
return array;
}
}
最終匯總時由于二人統(tǒng)計方法存于不同容器授嘀,因此遍歷方法不一致物咳,需各自遍歷,如下:
public static void main(String[] args) {
public static void main(String[] args) {
Min min = new Min();
List<Employee> list = min.getList();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}
System.out.println("===================================================");
Hui hui = new Hui();
Employee[] array = hui.getArray();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i].toString());
}
/**
Emplyee{name=lilei,age=18,sex=male,job=job1}
Emplyee{name=hanmeimei,age=28,sex=female,job=job2}
Emplyee{name=lily,age=24,sex=female,job=job0}
Emplyee{name=tantong,age=42,sex=male,job=job0}
===================================================
Emplyee{name=green,age=39,sex=male,job=job0}
Emplyee{name=lucy,age=20,sex=female,job=job1}
Emplyee{name=lancy,age=16,sex=female,job=job2}
Emplyee{name=jacky,age=35,sex=male,job=job1}
*/
下面使用迭代器模式修改上述代碼蹄皱,首先員工信息類不需要改變览闰,然后定義一個遍歷容器數(shù)據(jù)元素的方法,接口如下:
public interface EmployeeIterator<T> {
boolean hasNext();
T next();
}
接著讓Min和Hui兩個容器類分別實現(xiàn)該接口巷折,讓它們對外提供遍歷方法next():
public static class MinIterator implements EmployeeIterator<Employee> {
private List<Employee> list;
private int cursor = 0;
public MinIterator(List<Employee> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return !(cursor > list.size() - 1 || list.get(cursor) == null);
}
@Override
public Employee next() {
return list.get(cursor++);
}
}
public static class HuiIterator implements EmployeeIterator<Employee> {
private Employee[] array;
private int cursor = 0;
public HuiIterator(Employee[] array) {
this.array = array;
}
@Override
public boolean hasNext() {
return !(cursor > array.length - 1 || array[cursor] == null);
}
@Override
public Employee next() {
return array[cursor++];
}
}
到這里就關鍵了压鉴,主角迭代器登場!定義一個第三者——迭代器锻拘,代碼如下油吭,分別讓Min和Hui實現(xiàn)該接口對外提供獲取迭代器接口方法,代碼如下:
public interface Company {
EmployeeIterator iterator();
}
public static class CompanyMin implements Company {
private List<Employee> list = new ArrayList<>();
private Employee lilei = new Employee("lilei", 18, "male", "job1");
private Employee hanmeimei = new Employee("hanmeimei", 28, "female", "job2");
private Employee lily = new Employee("lily", 24, "female", "job0");
private Employee tantong = new Employee("tantong", 42, "male", "job0");
public CompanyMin() {
list.add(lilei);
list.add(hanmeimei);
list.add(lily);
list.add(tantong);
}
@Override
public EmployeeIterator iterator() {
return new MinIterator(list);
}
}
public static class CompanyHui implements Company {
private Employee[] array = new Employee[4];
private Employee green = new Employee("green", 39, "male", "job0");
private Employee lucy = new Employee("lucy", 20, "female", "job1");
private Employee lancy = new Employee("lancy", 16, "female", "job2");
private Employee jacky = new Employee("jacky", 35, "male", "job1");
public CompanyHui() {
array[0] = green;
array[1] = lucy;
array[2] = lancy;
array[3] = jacky;
}
@Override
public EmployeeIterator iterator() {
return new HuiIterator(array);
}
}
最終匯總信息如下:
public static void main(String[] args) {
CompanyMin companyMin = new CompanyMin();
EmployeeIterator minIterator = companyMin.iterator();
showDetail(minIterator);
System.out.println("===================================================");
CompanyHui companyHui = new CompanyHui();
EmployeeIterator huiIterator = companyHui.iterator();
showDetail(huiIterator);
/**
Emplyee{name=lilei,age=18,sex=male,job=job1}
Emplyee{name=hanmeimei,age=28,sex=female,job=job2}
Emplyee{name=lily,age=24,sex=female,job=job0}
Emplyee{name=tantong,age=42,sex=male,job=job0}
===================================================
Emplyee{name=green,age=39,sex=male,job=job0}
Emplyee{name=lucy,age=20,sex=female,job=job1}
Emplyee{name=lancy,age=16,sex=female,job=job2}
Emplyee{name=jacky,age=35,sex=male,job=job1}
*/
}
private static void showDetail(EmployeeIterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}
}
從使用迭代器模式修改后的方案來看署拟,盡管Min婉宰、Hui二人統(tǒng)計數(shù)據(jù)存于不同容器,但是已讓這兩個不同容器實現(xiàn)共同遍歷接口EmployeeIterator推穷,共同對外提供next方法心包,這樣就實現(xiàn)了在即不用容器封裝遍歷方法,也不暴露容器內部實現(xiàn)細節(jié)的情況下缨恒,完成了對容器數(shù)據(jù)元素的遍歷谴咸。