1. ما هو نمط الكومبوزيت
نمط الكومبوزيت هو نمط هيكلي للأشياء المستخدم بشكل شائع. يجمع بين الأشياء في هيكل شجري لتمثيل "الجزء - الكل" التسلسلي، مما يسمح للعملاء بالتعامل مع الأشياء الفردية وتكوين الأشياء بطريقة متسقة.
2. خصائص ومزايا نمط الكومبوزيت
المزايا الرئيسية لنمط الكومبوزيت هي:
- يمكن تحديد الأشياء الهرمية المعقدة بوضوح، ممثلة كل الهرم أو جزء من الهرم، مما يجعل من السهل إضافة مكونات جديدة.
- يوفر واجهة موحدة، مما يجعل الوصول إلى الأجزاء الكومبوزيت والأشياء الفردية متسقًا، ويمكن للعملاء استخدام الأشياء الفردية والكومبوزيت بشكل موحد.
3. سيناريوهات تطبيق نمط الكومبوزيت
- عندما ترغب في تمثيل التسلسل "الجزء - الكل" للأشياء.
- عندما ترغب في أن يتجاهل العملاء الاختلافات بين الأشياء الكومبوزيت والأشياء الفردية، ويستخدمون جميع الأشياء في الهيكل الكومبوزيت بشكل موحد.
4. تنفيذ نمط الكومبوزيت في Golang
لنفترض أننا نصمم تطبيق تجارة إلكترونية، فهناك فئة المنتجات مثال جيد لنمط الكومبوزيت. يمكن للفئة أن تحتوي على فئات أخرى، وأيضًا منتجات (مثل فئة الإلكترونيات تحتوي على هواتف، أجهزة كمبيوتر، والهواتف تحتوي على آيفون، هواتف سامسونج، إلخ).
4.1 رسم بياني للفصل UML
4.2 مقدمة للمثال
في هذا المثال، لدينا Component
(بوضوح نستخدم ميزة الواجهة للتوجيه الكائن) كفئة أساسية مجردة، وComposite
وLeaf
يقومان بتنفيذ هذه الواجهة، تمثل الكائنات المحتوية والكائنات الأساسية على التوالي.
4.3 تنفيذ الخطوة 1: تعريف فئة الكائن المجرد
4.3.1 تحديد واجهة فئة الكائن المجرد
// Component: واجهة العنصر الأساسي، تعرف الشمولية للمجموعات والأفراد
type Component interface {
Search(string)
}
4.3.2 تنفيذ الأساليب الأساسية لفئة الكائن المجرد
يتم تنفيذ هذه الخطوة خصيصًا في فئة العنصر المحتوي وفئة العنصر الورقي.
4.4 تنفيذ الخطوة 2: تعريف فئة العنصر الورقي
تمثل هذه الفئة المحددة الفئة السفلية أو الكائن في التسلسل، ولا يوجد لديها طبقة الكائنات التالية.
4.4.1 الوراثة من فئة العنصر المجرد
في Go، يتم تنفيذ الوراثة من الواجهة عن طريق طريقة تنفيذ الأساليب من خلال Struct.
4.4.2 تنفيذ الأساليب المحددة لفئة العنصر الورقي
// Product: يمثل عقدة ورقية، أي منتج، ولا يمكن أن يحتوي على عقدات فرعية
type Product struct {
Name string
}
// Search: البحث عن المنتجات
func (p *Product) Search(keyword string) {
if strings.Contains(p.Name, keyword) {
fmt.Printf("المنتج: '%s' يحتوي على الكلمة: '%s'\n", p.Name, keyword)
}
}
4.5 تنفيذ الخطوة 3: تعريف فئة العنصر المحتوي
يتم استخدام هذه الفئة لتخزين وإدارة الكائنات الفرعية، بما في ذلك بعض الأساليب لإدارة وتنظيم الكائنات الفرعية، مثل add(Component)
، remove(Component)
، إلخ.
4.5.1 الوراثة من فئة العنصر المجرد
يتم تنفيذ هذا أيضًا باستخدام Struct لتنفيذ أساليب الواجهة في Go.
4.5.2 تنفيذ الأساليب المحددة لفئة العنصر المحتوي
// Category: يمثل عقدة محتوية، أي فئة المنتج، والتي يمكن أن تحتوي على عقدات فرعية
type Category struct {
Name string
Children []Component
}
// Add: أضف عقدة فرعية
func (c *Category) Add(child Component) {
c.Children = append(c.Children, child)
}
// Remove: أزل عقدة فرعية
func (c *Category) Remove(child Component) {
// ترك التنفيذ المحدد
}
// Search: البحث عن المنتجات
func (c *Category) Search(keyword string) {
fmt.Printf("الفئة: %s\n", c.Name)
for _, composite := range c.Children {
composite.Search(keyword)
}
}
4.6 تنفيذ الخطوة 4: مثال على كود العميل
قم بإنشاء هيكل، وتجميعه في هيكل شجري، ثم استدعاء عملية الوصول إلى هيكل الشجرة.
func main() {
root := &Category{Name: "Root"}
electronics := &Category{Name: "Electronics"}
phone := &Product{Name: "Phone"}
tv := &Product{Name: "Television"}
root.Add(electronics)
electronics.Add(phone)
electronics.Add(tv)
root.Search("phone") // سيبحث هذا في جميع الأطفال
}