1. چیست الگوی Iterator
الگوی Iterator یک الگوی طراحی رفتاری است که یک روش یکپارچه برای گذر از عناصر یک شیء تجمعی را بدون افشای نمایش داخلی شیء تجمعی فراهم میکند.
2. ویژگیها و مزایای الگوی Iterator
ویژگیها و مزایای الگوی Iterator به شرح زیر است:
- میتواند ساختار داخلی شیء مجموعه را مخفی کند و الگوریتم گذر را از شیء مجموعه جدا کند.
- روش استانداردی برای گذر از انواع مختلف اشیاء مجموعه فراهم میآورد.
- کد مشتری را سادهتر و مفهومیتر میکند.
- میتواند انواع مختلف Iteratorها را فراهم کند تا با نیازهای گذر مختلف سازگار شود.
3. نمونههای کاربردی عملی از الگوی Iterator
الگوی Iterator کاربردهای عملی بسیاری دارد، مانند:
- گذر از مجموعه نتایج پرس و جوی پایگاه داده.
- گذر از فایلها و پوشهها در سیستم فایل.
- گذر از عناصر در یک مجموعه.
4. پیادهسازی الگوی Iterator در Golang
4.1 نمودار کلاس UML
4.2 معرفی نمونه
در نمودار کلاس UML بالا، دو نقش اصلی داریم: Iterator و Collection.
- Iterator رابط را برای گذر از یک شیء مجموعه تعریف میکند که شامل متد
HasNext()
برای تعیین وجود عنصر دیگر و متدNext()
برای گرفتن عنصر بعدی است. - ConcreteIterator کلاس اجرایی خاص Iterator است که متد
HasNext()
وNext()
را پیادهسازی میکند. - Collection رابط را برای ایجاد اشیاء Iterator، با متد
CreateIterator()
، تعریف میکند. - ConcreteCollection کلاس اجرایی خاص Collection است که متد
CreateIterator()
را پیادهسازی میکند.
4.3 مراحل پیادهسازی
بعداً، ما الگوی Iterator را به زبان Golang گام به گام پیادهسازی خواهیم کرد.
4.3.1 تعریف رابط Iterator و کلاس Concrete Iterator
type Iterator interface {
HasNext() bool
Next() interface{}
}
type ConcreteIterator struct {
collection *ConcreteCollection
index int
}
func (it *ConcreteIterator) HasNext() bool {
if it.index < len(it.collection.items) {
return true
}
return false
}
func (it *ConcreteIterator) Next() interface{} {
if it.HasNext() {
item := it.collection.items[it.index]
it.index++
return item
}
return nil
}
4.3.2 تعریف رابط شیء Iterable و کلاس شیء Iterable Concrete
type Collection interface {
CreateIterator() Iterator
}
type ConcreteCollection struct {
items []interface{}
}
func (c *ConcreteCollection) CreateIterator() Iterator {
return &ConcreteIterator{
collection: c,
index: 0,
}
}
4.3.3 پیادهسازی منطق تولید Iterator در کلاس شیء Iterable
func main() {
collection := &ConcreteCollection{
items: []interface{}{"Golang", "Python", "Java"},
}
iterator := collection.CreateIterator()
for iterator.HasNext() {
item := iterator.Next()
fmt.Println(item)
}
}
اجرای کد بالا خروجی زیر را تولید خواهد کرد:
Golang
Python
Java
در کد بالا، ما یک کلاس ConcreteCollection
را تعریف میکنیم که رابط Collection
را پیادهسازی میکند، و با متد CreateIterator()
اشیاء Iterator را برمیگرداند. ما از این اشیاء Iterator در تابع main()
برای گذر استفاده میکنیم.
4.4 گام اجرایی گسترش: سادهسازی پیادهسازی ایتریتور با استفاده از تابع تولید کننده
در Golang، میتوانیم با استفاده از تابع تولید کننده (yield
)، پیادهسازی ایتریتورها را سادهتر کنیم. در ادامه، یک مثال از استفاده از تابع تولید کننده آمده است:
func GenerateItems() <-chan interface{} {
items := []interface{}{"Golang", "Python", "Java"}
out := make(chan interface{})
go func() {
defer close(out)
for _, item := range items {
out <- item
}
}()
return out
}
func main() {
for item := range GenerateItems() {
fmt.Println(item)
}
}
در کد فوق، یک تابع به نام GenerateItems()
تعریف شده است که یک کانال فقط‐خواندنی (<-chan
) را برمیگرداند و از yield
برای به ترتیب ارسال عناصر به کانال درون این تابع استفاده میکند. در تابع main()
، از range
برای گذر از این کانال فقط‐خواندنی و خروجی دادن مقادیر عناصر استفاده میشود.
به این ترتیب، ما پیادهسازی ایتریتور را با استفاده از یک تابع تولید کننده سادهسازی کردهایم.