Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط Abstract Factory

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 88 من 107.

يوسع نمط المصنع المجرد (Abstract Factory pattern) نمط المصنع (Factory pattern) من خلال إنشاء عائلات من الكائنات المرتبطة دون تحديد أنواعها الملموسة. فبدلاً من دالة مصنع واحدة، تقوم بتعريف واجهة مصنع (factory interface) تقوم عدة مصانع ملموسة (concrete factories) بتنفيذها، حيث ينتج كل منها مجموعة متسقة من الكائنات المرتبطة.

فكر في مجموعة أدوات واجهة مستخدم (UI toolkit) تحتاج إلى إنشاء أزرار وخانات اختيار. تتطلب أنظمة التشغيل المختلفة عمليات تنفيذ مختلفة، ولكن يجب أن تعمل المكونات معًا بشكل متسق:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// واجهة المصنع المجرد (Abstract factory interface)
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

ينتج كل مصنع محدد عائلة من المكونات المرتبطة:

// عائلة Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// عائلة Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

يعمل كود العميل مع واجهة المصنع، ويظل مستقلاً عن التنفيذات الملموسة:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

استخدم نمط المصنع المجرد (Abstract Factory) عندما يحتاج نظامك للعمل مع عائلات متعددة من المنتجات ذات الصلة وتريد التأكد من استخدام المكونات من نفس العائلة معًا. إنه أكثر تعقيدًا من نمط المصنع (Factory) البسيط، لذا لا تلجأ إليه إلا عندما تحتاج حقًا إلى إدارة عائلات المنتجات.

challenge icon

التحدي

سهل

لنقم ببناء نظام لمتجر أثاث باستخدام نمط المصنع المجرد (Abstract Factory pattern)! ستقوم بإنشاء مصانع تنتج عائلات من قطع الأثاث المترابطة—كل مصنع ينتج نمطاً متسقاً (Modern أو Vintage)، مما يضمن أن الكراسي والطاولات من نفس المصنع تتطابق جمالياً.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • furniture.go: حدد واجهات المنتجات (product interfaces) وأنواع الأثاث الملموسة (concrete furniture types).

    أنشئ واجهتين للمنتجات:

    • Chair مع طريقة SitOn() string
    • Table مع طريقة PlaceItems() string

    قم بتنفيذ عائلتين من الأثاث:

    • عائلة Modern: تعيد ModernChair القيمة "Sitting on a sleek modern chair" وتعيد ModernTable القيمة "Placing items on a glass modern table"
    • عائلة Vintage: تعيد VintageChair القيمة "Sitting on an ornate vintage chair" وتعيد VintageTable القيمة "Placing items on a wooden vintage table"
  • factory.go: حدد واجهة المصنع المجرد (abstract factory interface) والمصانع الملموسة (concrete factories).

    أنشئ واجهة FurnitureFactory مع طريقتين:

    • CreateChair() Chair
    • CreateTable() Table

    قم بتنفيذ مصنعين ملموسين:

    • ModernFactory الذي ينتج ModernChair و ModernTable
    • VintageFactory الذي ينتج VintageChair و VintageTable

    قم أيضاً بإنشاء دالة GetFactory(style string) FurnitureFactory التي تعيد المصنع المناسب بناءً على النمط ("modern" أو "vintage"). اجعل ModernFactory هو الافتراضي للأنماط غير المعترف بها.

  • main.go: استخدم مصانعك لتأثيث الغرف.

    أنشئ دالة FurnishRoom(factory FurnitureFactory) string تستخدم المصنع لإنشاء كرسي وطاولة، ثم تعيد سلسلة نصية منسقة تعرض كلا الإجراءين في سطرين منفصلين.

    اقرأ مدخلاً للنمط، واحصل على المصنع المناسب، وقم بتأثيث غرفة، واطبع النتيجة.

سيتم توفير المدخلات التالية:

  • السطر 1: نمط الأثاث ("modern"، "vintage"، أو شيء آخر)

على سبيل المثال، إذا كان المدخل:

modern

يجب أن يكون مخرجك:

Sitting on a sleek modern chair
Placing items on a glass modern table

وإذا كان المدخل:

vintage

يجب أن يكون مخرجك:

Sitting on an ornate vintage chair
Placing items on a wooden vintage table

وإذا كان المدخل:

rustic

يجب أن يكون مخرجك:

Sitting on a sleek modern chair
Placing items on a glass modern table

لاحظ كيف تعمل دالة FurnishRoom مع أي مصنع من خلال الواجهة—فهي لا تعرف ما إذا كانت تنشئ أثاثاً حديثاً (modern) أم عتيقاً (vintage). يضمن ذلك أن جميع الأثاث في الغرفة يأتي من نفس العائلة، مما يحافظ على نمط متسق!

ورقة مرجعية

يقوم نمط المصنع المجرد (Abstract Factory pattern) بإنشاء عائلات من الكائنات المرتبطة دون تحديد أنواعها الملموسة. فهو يحدد واجهة مصنع تقوم عدة مصانع ملموسة بتنفيذها، حيث ينتج كل منها مجموعة متسقة من الكائنات المرتبطة.

الهيكل

قم بتعريف واجهات المنتجات لكل نوع من الكائنات:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

قم بإنشاء واجهة مصنع مجردة تعلن عن طرق لإنشاء كل نوع من المنتجات:

type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

التنفيذات الملموسة

قم بتنفيذ عائلات المنتجات الملموسة حيث يكون لكل عائلة تنسيق أو سلوك متسق:

// عائلة Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// عائلة Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

كود العميل

يعمل كود العميل مع واجهة المصنع، ويظل مستقلاً عن التنفيذات الملموسة:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

متى يُستخدم

استخدم المصنع المجرد (Abstract Factory) عندما يحتاج نظامك إلى العمل مع عائلات متعددة من المنتجات ذات الصلة وتريد التأكد من استخدام المكونات من نفس العائلة معاً. إنه أكثر تعقيداً من المصنع البسيط، لذا استخدمه فقط عندما تحتاج حقاً إلى إدارة عائلات المنتجات.

جرّب بنفسك

package main

import "fmt"

// تستخدم FurnishRoom مصنعاً لإنشاء الأثاث وإرجاع النتيجة
// TODO: قم بتنفيذ هذه الدالة
// - استخدم المصنع لإنشاء كرسي وطاولة
// - أرجع سلسلة نصية تحتوي على نتيجة SitOn() في السطر الأول ونتيجة PlaceItems() في السطر الثاني
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: قم بإنشاء كرسي وطاولة باستخدام المصنع
	// TODO: أرجع سلسلة نصية منسقة مع كلا الإجراءين في أسطر منفصلة
	return ""
}

func main() {
	var style string
	fmt.Scanln(&style)

	// TODO: احصل على المصنع المناسب بناءً على النمط
	// TODO: قم بتأثيث غرفة باستخدام المصنع
	// TODO: اطبع النتيجة
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming

13أنماط التصميم - الجزء الأول

مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy