- 一文带你搞懂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());
}
}
}