From 4f6f5032606ce2c53a3af9b3b5c2b73a03fa9913 Mon Sep 17 00:00:00 2001 From: Edward Date: Sun, 3 May 2020 19:33:03 +0800 Subject: [PATCH] add two iterator patterns examples --- .../book_iterator/book_iterator.go | 91 +++++++++++++++++++ .../book_iterator/book_iterator_test.go | 22 +++++ .../04_iterator/person_iterator/iterator.go | 72 +++++++++++++++ .../person_iterator/iterator_test.go | 18 ++++ 4 files changed, 203 insertions(+) create mode 100644 behavior/04_iterator/book_iterator/book_iterator.go create mode 100644 behavior/04_iterator/book_iterator/book_iterator_test.go create mode 100644 behavior/04_iterator/person_iterator/iterator.go create mode 100644 behavior/04_iterator/person_iterator/iterator_test.go diff --git a/behavior/04_iterator/book_iterator/book_iterator.go b/behavior/04_iterator/book_iterator/book_iterator.go new file mode 100644 index 0000000..7ffb0ff --- /dev/null +++ b/behavior/04_iterator/book_iterator/book_iterator.go @@ -0,0 +1,91 @@ +// Package iterator is an example of the Iterator Pattern. +package iterator + +// Iterator provides a iterator interface. +type Iterator interface { + Index() int + Value() interface{} + Has() bool + Next() + Prev() + Reset() + End() +} + +// Aggregate provides a collection interface. +type Aggregate interface { + Iterator() Iterator +} + +// BookIterator implements the Iterator interface. +type BookIterator struct { + shelf *BookShelf + index int + internal int +} + +// Index returns current index +func (i *BookIterator) Index() int { + return i.index +} + +// Value returns current value +func (i *BookIterator) Value() interface{} { + return i.shelf.Books[i.index] +} + +// Has implementation. +func (i *BookIterator) Has() bool { + if i.internal < 0 || i.internal >= len(i.shelf.Books) { + return false + } + return true +} + +// Next goes to the next item. +func (i *BookIterator) Next() { + i.internal++ + if i.Has() { + i.index++ + } +} + +// Prev goes to the previous item. +func (i *BookIterator) Prev() { + i.internal-- + if i.Has() { + i.index-- + } +} + +// Reset resets iterator. +func (i *BookIterator) Reset() { + i.index = 0 + i.internal = 0 +} + +// End goes to the last item. +func (i *BookIterator) End() { + i.index = len(i.shelf.Books) - 1 + i.internal = i.index +} + +// BookShelf implements the Aggregate interface. +type BookShelf struct { + Books []*Book +} + +// Iterator creates and returns the iterator over the collection. +func (b *BookShelf) Iterator() Iterator { + return &BookIterator{shelf: b} +} + +// Add adds an item to the collection. +func (b *BookShelf) Add(book *Book) { + b.Books = append(b.Books, book) +} + +// Book implements a item of the collection. +type Book struct { + Name string +} diff --git a/behavior/04_iterator/book_iterator/book_iterator_test.go b/behavior/04_iterator/book_iterator/book_iterator_test.go new file mode 100644 index 0000000..636db76 --- /dev/null +++ b/behavior/04_iterator/book_iterator/book_iterator_test.go @@ -0,0 +1,22 @@ +// Package iterator is an example of the Iterator Pattern. +package iterator + +import "testing" + +func TestIterator(t *testing.T) { + + shelf := new(BookShelf) + + books := []string{"A", "B", "C", "D", "E", "F"} + + for _, book := range books { + shelf.Add(&Book{Name: book}) + } + + for iterator := shelf.Iterator(); iterator.Has(); iterator.Next() { + index, value := iterator.Index(), iterator.Value().(*Book) + if value.Name != books[index] { + t.Errorf("Expect Book.Name to %s, but %s", books[index], value.Name) + } + } +} diff --git a/behavior/04_iterator/person_iterator/iterator.go b/behavior/04_iterator/person_iterator/iterator.go new file mode 100644 index 0000000..13a3eae --- /dev/null +++ b/behavior/04_iterator/person_iterator/iterator.go @@ -0,0 +1,72 @@ +package iterator + +import "fmt" + +/* + 设计思想: + 1. Iterator结构体 + 实现Next() HasNext()方法 + 2. Container容器 + 容器实现添加 移除Visitor 和 +*/ +//创建迭代器 +type Iterator struct { + index int + Container +} + +func (i *Iterator) Next() Visitor { + fmt.Println(i.index) + visitor := i.list[i.index] + i.index += 1 + return visitor +} + +func (i *Iterator) HasNext() bool { + if i.index >= len(i.list) { + return false + } + return true +} + +//创建容器 +type Container struct { + list []Visitor +} + +func (c *Container) Add(visitor Visitor) { + c.list = append(c.list, visitor) +} + +func (c *Container) Remove(index int) { + if index < 0 || index > len(c.list) { + return + } + c.list = append(c.list[:index], c.list[index+1:]...) +} + +//创建Visitor接口 +type Visitor interface { + Visit() +} + +//创建具体的visitor对象 +type Teacher struct{} + +type Analysis struct{} + +func (t *Teacher) Visit() { + fmt.Println("this is teacher visitor") +} + +func (a *Analysis) Visit() { + fmt.Println("this is analysis visitor") +} + +//工厂方法创建迭代器 +func NewIterator() *Iterator { + return &Iterator{ + index: 0, + Container: Container{}, + } +} diff --git a/behavior/04_iterator/person_iterator/iterator_test.go b/behavior/04_iterator/person_iterator/iterator_test.go new file mode 100644 index 0000000..add615b --- /dev/null +++ b/behavior/04_iterator/person_iterator/iterator_test.go @@ -0,0 +1,18 @@ +package iterator + +import "testing" + +func TestIterator_Next(t *testing.T) { + teacher := new(Teacher) + analysis := new(Analysis) + //迭代器 + iterator := NewIterator() + iterator.Add(teacher) + iterator.Add(analysis) + if len(iterator.list) != 2 { + t.Error("期望的count is 2") + } + for iterator.HasNext() { + iterator.Next().Visit() + } +}