1.定义
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
主要包括以下几个角色:
- 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
- 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
- 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
- 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置
2.理解
就如同我们使用java的List一样,它提供了对应的Iterator对象,我们可以通过这个迭代器完成对list的访问。从定义上来看,提供了迭代器对象后,最好将聚合对象的实际表示隐藏起来,让使用者只能通过迭代器去访问。
3.示例介绍
下面我将用这样的例子来实现一个迭代器模式的代码。
书。聚合角色中的具体元素
书架。抽象聚合角色。里面有加入书功能和获得迭代器方法。
我的书架。具体聚合角色。
抽象迭代器。next()方法和hasNext()方法
具体迭代器。
4.java实现
public class IteratorPattern {
public static void main(String[] args) {
Book book1 = new Book();
book1.setName("book 1");
Book book2 = new Book();
book2.setName("book 2");
//新建一个具体聚合对象,并聚合一些元素
BookShlef shlef = new MyBookShlef();
shlef.add(book1).add(book2);
//提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
//现在我们无法直接通过shelf对内部的元素进行访问,只能通过迭代器
MyIterator<Book> iterator = shlef.getIterator();
while(iterator.hasNext()){
Book next = iterator.next();
System.out.println(next.getName());
}
}
}
//抽象聚合
interface BookShlef{
MyIterator<Book> getIterator();
BookShlef add(Book b);
}
//抽象迭代器
interface MyIterator<T>{
T next();
boolean hasNext();
}
@Data
class Book{
private String name;
}
class MyBookShlef implements BookShlef{
//迭代器的关键:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示,这里就是私有的内部数据
private List<Book> list= new ArrayList<Book>();
@Override
public MyIterator<Book> getIterator() {
BookIterator iterator = new BookIterator(this);
return iterator;
}
@Override
public BookShlef add(Book b) {
this.list.add(b);
return this;
}
//具体迭代器:这里采用了内部类的方式,以方便访问具体聚合中的私有数据。
class BookIterator implements MyIterator<Book>{
private MyBookShlef bookShlef;
private int index;
public BookIterator(MyBookShlef bookShlef){
this.bookShlef = bookShlef;
}
@Override
public Book next() {
int size = this.bookShlef.list.size();
if (size == 0 || index >= size){
throw new RuntimeException("下标越界");
}
return this.bookShlef.list.get(index++);
}
@Override
public boolean hasNext() {
int size = this.bookShlef.list.size();
if (size > 0 && index<size){
return true;
}
return false;
}
}
}
5.golang实现
func main() {
book1:=&Book{Name: "book1"}
book2:=&Book{Name: "book2"}
shelf := new(MyBookShlef)
shelf.Add(book1)
shelf.Add(book2)
iterator := shelf.GetIterator()
for iterator.HasNext(){
ele := iterator.Next().Ele
book := ele.(*Book)
fmt.Println(book.Name)
}
}
//一个统一的接口,用Element包装了下,这样,该迭代器接口可以给给多的具体迭代器使用。
//因为golang中无泛型,因此相比java麻烦了些
type MyIterator interface {
Next() *Element
HasNext() bool
}
type Element struct{
Ele interface{}
}
type BookShelf interface {
GetIterator() MyIterator
Add(book *Book)
}
type MyBookShlef struct {
list []*Book // 私有
}
func (bookShelf *MyBookShlef) GetIterator() MyIterator {
bookIterator := new(BookIterator)
bookIterator.list = bookShelf.list
bookIterator.index = 0
return bookIterator
}
func (bookShelf *MyBookShlef) Add(book *Book) {
bookShelf.list = append(bookShelf.list, book)
}
type BookIterator struct {
//bookShelf BookShelf // 持有一个聚合类的引用,以访问它里面的数据,因为被私有化了,所以不能通过这种方式了
list []*Book // 持有聚合类里面数据的引用也是可以的
index int
}
func (iterator *BookIterator) HasNext() bool {
size := len(iterator.list)
if size > 0 && iterator.index < size{
return true
}
return false
}
func (iterator *BookIterator) Next() *Element{
if !iterator.HasNext(){
panic (errors.New("下标越界"))
}
book := iterator.list[iterator.index]
iterator.index++
return &Element{Ele: book}
}
type Book struct {
Name string
}