【设计模式】17、iterator 迭代器模式

本文详细介绍了Go语言中iterator模式的应用,通过UserSlice和BookShelf实例展示如何使用迭代器接口,分别基于数组和链表实现数据结构的遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


十七、iterator 迭代器模式

https://refactoringguru.cn/design-patterns/iterator

为了集合数据的安全性, 或方便迭代, 可以用迭代器接口. 屏蔽复杂的内部逻辑, 外部只能使用迭代器遍历

源码路径:godp/17iterator at master · datager/godp · GitHub

17.1 user_slice

├── collection.go
├── collection_test.go
├── iterator.go
├── readme.md
└── user.go

17.1.1 collection_test.go

package _71user_slice

import (
    "fmt"
    "testing"
)

/*
=== RUN   TestCollection
1 Tom
2 Jack
--- PASS: TestCollection (0.00s)
PASS
*/
func TestCollection(t *testing.T) {
    c := UserCollection{users: []*User{&User{"1", "Tom"}, {"2", "Jack"}}}
    iter := c.createIterator()
    for iter.hasNext() {
        v := iter.getNext()
        fmt.Println(v.ID, v.Name)
    }
}

17.1.2 collection.go

package _71user_slice

type Collection interface {
    createIterator() Iterator
}

type UserCollection struct {
    users []*User
}

func (uc *UserCollection) createIterator() Iterator {
    return &userIterator{
        users: uc.users,
    }
}

17.1.3 iterator.go

package _71user_slice

type Iterator interface {
    hasNext() bool
    getNext() *User
}

type userIterator struct {
    index int
    users []*User
}

func (ui *userIterator) hasNext() bool {
    return ui.index < len(ui.users)
}

func (ui *userIterator) getNext() *User {
    if ui.hasNext() {
        v := ui.users[ui.index]
        ui.index++
        return v
    }
    return nil
}

17.1.4 user.go

package _71user_slice

type User struct {
    ID   string
    Name string
}

17.2 book_shelf

图解设计模式 1.7 练习题

iterator 模式, 可以抽象出 迭代的操作, 无论内部数据结构是数组, 或链表, 或树, 都可以. 外部都可以用同样的接口访问.

本例, 分别用 数组, 和链表实现

├── book.go
├── book_shelf.go
├── book_shelf_test.go
├── iterator.go
└── readmd.md

17.2.1 book_shelf_test.go

package _72bookshelf

import (
	"github.com/stretchr/testify/require"
	"testing"
)

/*
=== RUN   TestBookShelf

	book_shelf_test.go:21: 算子开发
	book_shelf_test.go:21: 编译器
	book_shelf_test.go:21: 算子开发
	book_shelf_test.go:21: 编译器

--- PASS: TestBookShelf (0.00s)
PASS
*/
func TestBookShelf(t *testing.T) {
	bookShelves := []bookShelf{NewBookShelfBySlice(), NewBookShelfByList()}
	for _, bs := range bookShelves {
		bookNames := []string{"算子开发", "编译器"} // 测试数据
		for _, name := range bookNames {
			bs.addBook(NewBook(name))
		}

		it := bs.iterator()
		idx := 0
		for it.hasNext() {
			b := it.next()
			require.EqualValues(t, bookNames[idx], b.getName())
			t.Log(b.getName())
			idx++
		}
	}
}

17.2.2 book_shelf.go

package _72bookshelf

import "container/list"

// 书架接口
type bookShelf interface {
	// 创建迭代器
	iterator() iterator

	// 辅助业务:
	addBook(book)
}

// 书架: 数组实现
type bookShelfBySlice struct {
	books []book
}

func NewBookShelfBySlice() bookShelf {
	return &bookShelfBySlice{make([]book, 0)}
}

func (bs *bookShelfBySlice) iterator() iterator {
	return NewBookShelfBySliceIterator(bs)
}

func (bs *bookShelfBySlice) addBook(b book) {
	bs.books = append(bs.books, b)
}

// 书架: 链表实现
type bookShelfByList struct {
	bookList *list.List
}

func NewBookShelfByList() bookShelf {
	return &bookShelfByList{
		bookList: list.New(),
	}
}

func (bs *bookShelfByList) iterator() iterator {
	return NewBookShelfByListIterator(bs)
}

func (bs *bookShelfByList) addBook(b book) {
	bs.bookList.PushBack(b)
}

17.2.3 iterator.go

package _72bookshelf

import "container/list"

// 迭代器接口
type iterator interface {
	hasNext() bool
	next() book
}

// -------
// 书架迭代器: 基于数组的书架
type bookShelfBySliceIterator struct {
	index     int               // 迭代器下标
	bookShelf *bookShelfBySlice // 被迭代的对象
}

func (bsi *bookShelfBySliceIterator) hasNext() bool {
	return bsi.index < len(bsi.bookShelf.books)
}

func (bsi *bookShelfBySliceIterator) next() book {
	v := bsi.bookShelf.books[bsi.index]
	bsi.index++
	return v
}

func NewBookShelfBySliceIterator(bs *bookShelfBySlice) iterator {
	return &bookShelfBySliceIterator{bookShelf: bs, index: 0}
}

// -------
// 书架迭代器: 基于链表的书架
type bookShelfByListIterator struct {
	curBook   *list.Element    // 迭代器下标
	bookShelf *bookShelfByList // 被迭代的对象
}

func (bsl *bookShelfByListIterator) hasNext() bool {
	return bsl.curBook != nil
}

func (bsl *bookShelfByListIterator) next() book {
	v := bsl.curBook
	bsl.curBook = bsl.curBook.Next()
	return v.Value.(book)
}

func NewBookShelfByListIterator(bs *bookShelfByList) iterator {
	return &bookShelfByListIterator{bookShelf: bs, curBook: bs.bookList.Front()}
}

17.2.4 book.go

package _72bookshelf

import (
	"math/rand"
	"time"
)

type book interface {
	getName() string
}

type bookImpl struct {
	id   int
	name string
}

func (b *bookImpl) getName() string {
	return b.name
}

func NewBook(name string) book {
	rand.NewSource(time.Now().UnixMilli())
	return &bookImpl{
		id:   rand.Int(),
		name: name,
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值