- 一文帶你搞懂Java動態代理
- 幾分鐘帶你搞懂策略模式
- 幾分鐘帶你搞懂觀察者模式
- 一文徹底搞明白工廠和抽象工廠
- 一文搞明白裝飾者模式
- 最全單例模式
- 幾段代碼搞明白命令模式
- 幾段代碼搞明白適配器模式
- 一看就懂的外觀模式
- 一看就懂的模版方法模式
- 幾段代碼搞懂迭代器模式
- 一文搞懂明白狀態模式
關於迭代器模式的定義,我就直接引用Head First了:迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。這裏的聚合就是我們常說的集合,迭代器模式能讓我們遍歷集合內的對象,而又無需暴露集合本身的存儲結構(如數組,鏈表,散列表等),把遍歷的任務封裝起來,放在迭代器對象上,使其與集合所在的對象解耦。那爲何要將遍歷的部分封裝起來?其目的是爲了讓類的職責變得單一,讓集合能更專注於自身職責的處理。具體看下:
迭代器模式
假如廠商有兩款智能設備產品,爲:智能音箱和智能空調,現廠商決定要打造智能生態系統,需要將兩款智能設備的用戶整合到一起。但由於兩個部門對於數據處理模塊都有着各自的考量,所以讓本次的合併困難重重(一個是List,一個是數組,兩者的接口方法不一致)
這是當前的智能音箱類:
public class SpeakerBox {
ArrayList<User> users = new ArrayList();
public void register(User user) {
users.add(user);
}
public ArrayList getUsers() {
return users;
}
/**
* 當然內部還有很多複雜的邏輯處理,
* 都依賴於此ArrayList容器,
* 導致無法輕易更改存儲結構。
*/
}
這是當前的智能空調類:
public class AirConditioner {
static final int MAX_USER_COUNT = 100;
User[] users = new User[MAX_USER_COUNT];
int curItemCount = 0;
public void register(User user) {
if (curItemCount >= MAX_USER_COUNT)
System.out.println("用戶超額!");
else {
users[curItemCount] = user;
curItemCount++;
}
}
public User[] getUsers() {
return users;
}
}
這是用戶信息類:
public class User {
private String ID;
public String getId() {
return ID;
}
}
兩部門老大經過一番商談,最後決定將用戶集合的迭代工作從各自的數據處理模塊中抽離出來,讓處理模塊的職責更單一些,以達到降低耦合的目的。個人認爲:此處所說的“迭代” 只是迭代器模式的標準形式,其實不僅僅是迭代,我們還能抽離出很多其他的操作,如插首、插尾,甚至自定義的操作等。我覺得它的意圖是給不同結構的集合,通過迭代器類,抽離出一套對外的統一的接口供用戶使用,讓用戶無需關心所處理的集合的結構表示,只需要針對Iterator 編程就可以。
這是兩部門抽離出的迭代器接口類(當然也可以使用Java 自帶的java.util.Iterator 適配器接口,這裏就直接使用自定義的了)。
public interface Iterator {
boolean hasNext();
Object next();
}
這是智能音箱部門實現的音箱適配器類:
public class SpeakerBoxIterator implements Iterator {
ArrayList<User> users;
int curItemCount = 0;
int size;
public SpeakerBoxIterator(ArrayList<User> users) {
this.users = users;
if (null != this.users)
size = this.users.size;
}
@Override public boolean hasNext() {
return curItemCount < size;
}
@Override public Object next() {
if (curItemCount >= size)
return null;
else {
int cursor = curItemCount;
curItemCount++;
return users.get(cursor);
}
}
}
同理,這是智能空調部門實現的空調適配器類:
public class AirConditionerIterator implements Iterator {
User[] users;
int curItemCount = 0;
int length;
public AirConditionerIterator(User[] users) {
this.users = users;
if (null != this.users)
length = this.users.length;
}
@Override public boolean hasNext() {
return curItemCount < length;
}
@Override public Object next() {
if (curItemCount >= length)
return null;
else {
int cursor = curItemCount;
curItemCount++;
return users[cursor];
}
}
}
有了適配器類之後,我們再改造下我們的智能音箱類2.0,能夠看出,我們已經將迭代的責任移交給了 SpeakerBoxIterator 來處理,所以SpeakerBox 本身不需要再提供具體的迭代方法,也不需要對用戶暴露自身的集合類型。
public class SpeakerBox {
ArrayList<User> users = new ArrayList();
public void register(User user) {
users.add(user);
}
public Iterator creatIterator() {
return new SpeakerBoxIterator(users);
}
}
這是智能空調類2.0:
public class AirConditioner {
static final int MAX_USER_COUNT = 100;
User[] users = new User[MAX_USER_COUNT];
int curItemCount = 0;
public void register(User user) {
if (curItemCount >= MAX_USER_COUNT)
System.out.println("用戶超額!");
else {
users[curItemCount] = user;
curItemCount++;
}
}
public Iterator creatIterator() {
return new AirConditionerIterator(users);
}
}
這是我們的使用類,能夠發現ClientTest 並不需要知道音箱和空調類內部集合的類型,只需要針對Iterator 編程即可,通過creatIterator 方法就能夠遍歷集合內的每個元素。
public class ClientTest {
public static void main(String[] ags) {
// 將智能音箱和空調的用戶打印出來
Iterator sbIterator = speakerBox.creatIterator();
Iterator acIterator = airConditioner.creatIterator();
printInfo(sbIterator);
printInfo(acIterator);
}
private static void printInfo(Iterator iterator) {
while (iterator.hasNext()) {
User user = (User) iterator.next();
System.out.println("用戶ID: " + User.getId());
}
}
}