1. ما هو نمط المُستدِم (Iterator Pattern)
نمط المُستدِم هو نمط تصميمي سلوكي يوفر طريقة موحدة لعبور عناصر كائن جمعي بدون الكشف عن التمثيل الداخلي لكائن الجمع.
2. الخصائص والمزايا لنمط المُستدِم
الخصائص والمزايا لنمط المُستدِم كما يلي:
- يمكنه إخفاء الهيكل الداخلي لكائن الجمع، مُفككاً خوارزة عبور من كائن الجمع.
- يوفر طريقة موحدة لعبور أنواع مختلفة من كائنات الجمع.
- يُبسط كود العميل، مما يجعله أكثر وضوحاً وإيجازاً.
- يمكنه توفير تنفيذات مختلفة للمُستدِمات للتكيف مع احتياجات العبور المختلفة.
3. أمثلة لتطبيقات عُمَليّة لنمط المُستدِم
نمط المُستدِم له العديد من التطبيقات العُمَليّة، مثل:
- عبور مجموعة نتائج استعلام قاعدة البيانات.
- عبور الملفات والمجلدات في نظام الملفات.
- عبور العناصر في مجموعة.
4. تنفيذ نمط المُستدِم في جولانج (Golang)
4.1 مخطط الصفوف UML
4.2 مقدمة للمثال
في مخطط الصفوف UML أعلاه، لدينا دورين رئيسيين: المُستدِم والمجموعة.
- المُستدِم يعرِّف واجهة لعبور كائن مجموعة، بما في ذلك الطريقة
HasNext()
لتحديد ما إذا كان هناك عنصر آخر والطريقةNext()
للحصول على العنصر التالي. - المُستدِم_المحدد هو صنف التنفيذ المحدد للمُستدِم، حيث ينفذ الطرق
HasNext()
وNext()
. - المجموعة تعرِّف واجهة لإنشاء كائنات مُستدِم، بالطريقة
CreateIterator()
. - المجموعة_المحددة هي صنف التنفيذ المحدد للمجموعة، حيث ينفذ الطريقة
CreateIterator()
.
4.3 خطوات التنفيذ
بعد ذلك، سنقوم بتنفيذ نمط المُستدِم في جولانج خطوة بخطوة.
4.3.1 تعريف واجهة المُستدِم وصنف المُستدِم المحدد
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 تعريف واجهة كائن المجموعة وصنف كائن المجموعة المحدد
type Collection interface {
CreateIterator() Iterator
}
type ConcreteCollection struct {
items []interface{}
}
func (c *ConcreteCollection) CreateIterator() Iterator {
return &ConcreteIterator{
collection: c,
index: 0,
}
}
4.3.3 تنفيذ منطق توليدي المُستدِم في صنف كائن المجموعة
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()
كائن مُستدِم. نستخدم هذا الكائن المُستدِم في الدالة 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
لتصفح هذه القناة للقراءة فقط ونقوم بإخراج قيم العناصر.
بهذه الطريقة، لقد قمنا بتبسيط تنفيذ المكرر باستخدام وظيفة المولّد.