迭代器模式的定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
UML 图例
Iterator: 迭代器接口,定义访问和遍历元素的接口
ConcreateIterator:具体的迭代器实现对象,实现对聚合对象的遍历,并跟踪遍历时的当前位置
Aggreate:聚合对象,定义创建相应迭代器对象的接口。
ConcreteAggregate:具体聚合对象。实现创建相应的迭代器对象。
迭代器的关键思想
迭代器模式的关键思想就是聚合对象的遍历和访问从聚合对象中分离出来,放入单独的迭代器中
示例代码
Aggreate:
1 public abstract class Aggregate { 2 public abstract Interator createInterator(); 3 4 }
ConcreateIterator
public class ConcreteAggrgate extends Aggregate { private String[] ss = null;//聚合对象 public ConcreteAggrgate(String[] ss) { this.ss = ss; } @Override public Interator createInterator() { return new ConcreteIterator(this); } public Object get(int index) { Object retObj = null; if(index < ss.length) { retObj = ss[index]; } return retObj; } public int size() { return ss.length; } }
Iterator:
1 public interface Interator { 2 public void first(); 3 public void next(); 4 public boolean isDone(); 5 public Object currentItem(); 6 7 }
ConcreteIterator:
1 public class ConcreteIterator implements Interator { 2 3 private ConcreteAggrgate aggragte; 4 private int index = -1; 5 6 public ConcreteIterator(ConcreteAggrgate aggragte) { 7 this.aggragte = aggragte; 8 } 9 10 @Override 11 public void first() { 12 // TODO Auto-generated method stub 13 index = 0; 14 } 15 16 @Override 17 public void next() { 18 if (index < this.aggragte.size()) { 19 index++; 20 } 21 } 22 23 @Override 24 public boolean isDone() { 25 if(index == this.aggragte.size()) { 26 return true; 27 } 28 return false; 29 } 30 31 @Override 32 public Object currentItem() { 33 return this.aggragte.get(index); 34 } 35 36 }
Client
1 public class Clint { 2 3 public static void main(String[] args) { 4 String[] ss = { "张三", "李四", "王二狗", "康熙", "前童" }; 5 ConcreteAggrgate aggrgate = new ConcreteAggrgate(ss); 6 7 Interator interator = aggrgate.createInterator(); 8 interator.first(); 9 while(!interator.isDone()) { 10 System.out.println(interator.currentItem()); 11 interator.next(); 12 } 13 14 } 15 16 }
以上就是迭代器的示例代码
迭代器的模式的优点
1,更好的封装
2,迭代器模式可以让你访问一个聚合对象的内容,而无须暴露该聚合对象的内部表示,从而提高聚合对象的封装性
3,可以以不同的遍历方式来遍历一个聚合对象
4,使用迭代器模式,使得聚合对象的内容和具体的迭代算法分离开。这样就可以通过使用不同的迭代器的实例,不同的遍历方式来遍历一个聚合对象了。
5,迭代器简化了聚合的接口
6,有了迭代器的接口,则聚合本身就不需要在定义这些接口了,从而简化聚合的接口定义。
7,简化客户端调用
8,迭代器为遍历不同的聚合对象提供了一个统一的接口,使得客户端遍历聚合对象的内容变得更简单
9,同一个聚合上可以有多个遍历
10,每个迭代器保持它自己的遍历状态,比如前面实现中的迭代索引位置,因此可以对同一个聚合对象同时进行多个遍历
迭代器模式的本质
控制访问聚合对象中的元素
何时选用迭代器模式
1,如果你希望提供访问一个聚合对象的内容,但是又不想暴露它的内部实现的时候,可以使用迭代器模式来提供迭代器接口,
从而让客户端只是通过迭代器的接口来访问聚合对象,而无须关心聚合对象的内部实现
2,如果你希望有多种遍历方式可以访问聚合对象,可以使用迭代器模式。
3,如果你希望为遍历不同的聚合对象提供一个统一的接口,可以使用迭代器模式。
Android 中使用迭代器模式demo
翻页功能
Iterator
1 public interface MyIterator { 2 public boolean hasNext(); 3 public boolean hasPrevious(); 4 public Collection next(int num); 5 public Collection previous(int num); 6 7 }
CollectionIteratorImpl 实现类
1 public class CollectionIteratorImpl implements MyIterator { 2 3 private DataManager manager; 4 private int index = 0; 5 6 public CollectionIteratorImpl(DataManager manager) { 7 this.manager = manager; 8 } 9 10 @Override 11 public boolean hasNext() { 12 if (manager != null && index < manager.size()) { 13 return true; 14 } 15 return false; 16 } 17 18 @Override 19 public boolean hasPrevious() { 20 if (manager != null && index > 0) { 21 return true; 22 } 23 return false; 24 } 25 26 @Override 27 public Collection next(int num) { 28 List<Person> col = new ArrayList<>(); 29 int count = 0; 30 while (hasNext() && count < num) { 31 col.add(manager.get(index)); 32 count ++; 33 index ++; 34 } 35 return col; 36 } 37 38 @Override 39 public Collection previous(int num) { 40 List<Person> col = new ArrayList<>(); 41 int count = 0; 42 index = index - num; 43 while (hasPrevious() && count < num){ 44 col.add(manager.get(index)); 45 count ++; 46 index ++; 47 } 48 return col; 49 } 50 }
DataManager 聚合对象
1 public class DataManager { 2 3 private List<Person> mDatas = null; 4 5 public DataManager() { 6 mDatas = new ArrayList<>(); 7 for (int i = 0; i < 200; i++) { 8 mDatas.add(new Person("姓名"+i,i)); 9 } 10 } 11 12 13 public int size(){ 14 return mDatas.size(); 15 } 16 17 public Person get(int index) { 18 Person person = null; 19 if(index < size()) { 20 person = mDatas.get(index); 21 } 22 23 return person; 24 } 25 26 public MyIterator createInterator() { 27 return new CollectionIteratorImpl(this); 28 } 29 30 }
Activity 里面使用
1 public class IteratorActivity extends AppCompatActivity implements DropDownListView.OnListViewListener { 2 3 4 @Bind(R.id.mDropDownListView) 5 DropDownListView mDropDownListView; 6 private QuickAdapter mAdapter = null; 7 8 private List<Person> mDatas = null; 9 private MyIterator it; 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.activity_iterator); 15 ButterKnife.bind(this); 16 17 if (mAdapter == null) { 18 mAdapter = new QuickAdapter<Person>(this, R.layout.item) { 19 @Override 20 protected void convert(BaseAdapterHelper helper, Person item) { 21 helper.setText(R.id.container, item.getName() + " 年龄" + item.getAge()); 22 } 23 }; 24 } 25 26 DataManager dataManager = new DataManager(); 27 it = dataManager.createInterator(); 28 mDatas = (List<Person>) it.next(10); 29 mAdapter.addAll(mDatas); 30 31 mDropDownListView.clearFooterView(); 32 mDropDownListView.setCurrentOffset(mDatas.size()); 33 mDropDownListView.setOnNextPageListener(this); 34 mDropDownListView.setAdapter(mAdapter); 35 } 36 37 @Override 38 public void onNextPage() { 39 mDropDownListView.postDelayed(new Runnable() { 40 @Override 41 public void run() { 42 //每次从迭代器里面拿数据 43 List<Person> data = (List<Person>) it.next(10); 44 mAdapter.addAll( data); 45 mDropDownListView.setCurrentOffset(data.size()); 46 mAdapter.notifyDataSetChanged(); 47 } 48 },3000); 49 } 50 51 @Override 52 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 53 54 } 55 }
基本实现listview 翻页功能
分页基本上有两种实现方式
1,每次需要分页的时候请求网络拉去数据(时间换空间策略)
2,一次性拉去很多条,进行显示(空间换时间策略)
3,每次拉去多条,到了最后一页再从网络上拉去数据(迭代器使用场景,综合上面两种策略)
《研磨设计模式》笔记