设计模式 - 迭代器模式
场景
小张的朋友开了一家酒店,最近新收购了一家庭旅馆。需要对自己酒店的房间和家庭旅馆的房间进行统一管理,但是两家之间都有各自的实现存储房间,酒店使用的是list,而家庭旅馆使用的是数组,现在收购后想统一管理,但是由于两家的系统不一样,并且一直在生产,现在小张的朋友想统一管理两家的房间使客户能够统一进行订房。朋友找到了小张,让小张帮忙看看,如何处理。
场景分析
小张听了朋友的描述后,想着,现在两家的存储结构不同,一个使用集合list一个使用数组,现在想统一访问,如果统一一下两者的存储结构那么,就简单多了,但是朋友明确说了目前的情况是不能修改任何一方进行统一,对酒店和家庭旅馆分开遍历那么,如果有新的需要那么还需要在写一遍遍历,这样的话,能不能封装
遍历。
对于第三方来说,不想关心你的底层数据实现,只想要要遍历结果,那么迭代器是一个很好的解决方案。
在java的基础库中集合库(没有叫框架是因为java提供的集合是库,并不是框架)对每个数据结构都提供了统一遍历的方案,使你能够很方便的使用。
迭代器模式
先来看类图:
酒店接口
package xuelongjiang.designpartten.iterator;
/**
* 酒店接口
* @Author xuelongjiang
*/
public interface Hotel {
Iterator createIterator();//创建迭代器
}
迭代器接口
package xuelongjiang.designpartten.iterator;
/**
* 迭代器模式--- 封装集合
* @Author xuelongjiang
*/
public interface Iterator {
/**
* 判断是否有下一个元素
* @return
*/
boolean hasNext();
/**
* 遍历具体的一个元素
* @return
*/
Object next();
}
酒店类
package xuelongjiang.designpartten.iterator;
import java.util.ArrayList;
import java.util.List;
/**
* 酒店
* @Author xuelongjiang
*/
public class BusHotel implements Hotel {
List<String> homes;
public BusHotel() {
homes = new ArrayList<>();
homes.add("BusHotel--1");
homes.add("BusHotel--2");
homes.add("BusHotel--3");
homes.add("BusHotel--4");
homes.add("BusHotel--5");
homes.add("BusHotel--6");
}
@Override
public Iterator createIterator() {
return new BusHotelIterator(homes);
}
//其他的一些方法 .......
}
家庭旅馆类
package xuelongjiang.designpartten.iterator;
/**
* 家庭旅馆
* @Author xuelongjiang
*/
public class FamilyHotel implements Hotel {
String [] homes ;
public FamilyHotel() {
//家庭旅馆的房间
homes = new String [4];
homes[0] = "Familyhotel--1";
homes[1] = "Familyhotel--2";
homes[2] = "Familyhotel--3";
homes[3] = "Familyhotel--4";
}
@Override
public Iterator createIterator() {
return new FamilyHotelIterator(homes);
}
//其他的一些方法 ........
}
酒店迭代器
package xuelongjiang.designpartten.iterator;
import java.util.List;
/**
* 酒店迭代器
* @Author xuelongjiang
*/
public class BusHotelIterator implements Iterator {
List<String> homes; //酒店存储房间的数据结构
int position = 0;
public BusHotelIterator(List<String> homes) {
this.homes = homes;
}
@Override
public boolean hasNext() {
if(position>= homes.size()){
return false;
}
return true;
}
@Override
public Object next() {
String home = homes.get(position);
position = position+1;
return home;
}
}
家庭旅馆迭代器
package xuelongjiang.designpartten.iterator;
/**
* 家庭旅馆迭代器
* @Author xuelongjiang
*/
public class FamilyHotelIterator implements Iterator {
private String [] homes ;//家庭旅馆存储房间的数据结构
private int position = 0;
public FamilyHotelIterator(String[] homes) {
this.homes = homes;
}
@Override
public boolean hasNext() {
if(position >= homes.length || homes[position] == null ){
return false;
}
return true;
}
@Override
public Object next() {
String home = homes[position];
position = position + 1;
return home;
}
}
显示酒店和家庭旅馆的房间
package xuelongjiang.designpartten.iterator;
/**
*
* 统一遍历 酒店和家庭旅馆
* @Author xuelongjiang
*/
public class ShowHotel {
private BusHotel busHotel;
private FamilyHotel familyHotel;
public ShowHotel(BusHotel busHotel, FamilyHotel familyHotel) {
this.busHotel = busHotel;
this.familyHotel = familyHotel;
}
public void printHome(){
Iterator family = familyHotel.createIterator();
Iterator bus = busHotel.createIterator();
System.out.println("-------------family----------");
printHome(family);
System.out.println("---------------bus-----------");
printHome(bus);
}
public void printHome(Iterator iterator){
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
测试类
package xuelongjiang.designpartten.iterator;
/**
* 测试类
* @Author xuelongjiang
*/
public class IteratorTest {
public static void main(String[] args) {
ShowHotel showHotel = new ShowHotel(new BusHotel(),new FamilyHotel());
showHotel.printHome();
}
}
迭代器模式
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而有不是暴露其内部的表示。
我们上面的迭代器和java集合库的迭代器的区别是java集合迭代器是在每个数据结构(list,map,set,)类的内部使用内部类。上面的代码我们也可以把具体的迭代器声明到酒店和家庭旅馆内部作为内部类。
要点
内聚:用来度量一个类或模块紧密地达到单一目的或责任。
当一个模块或类被设计成只支持一组相关的功能时,我们说它具有高内聚(还害记得我们的口号吗)。
(区分设计中的责任,是最困难的事情之一)
- 迭代器允许访问聚合的元素,而不需要暴露它的内部结构。
- 迭代器将遍历聚合的工作封装进一个对象中。
- 我们应该努力让一个类只分配一个责任。