أنماط التصميم في Go مع أمثلة: من الألف إلى الياء
أنماط التصميم (Design Patterns) هي حلول معمارية مجربة عبر الزمن تساعد مطوري Go في إنشاء كود مرن وقابل للتوسع والصيانة. على عكس لغات البرمجة الكائنية التقليدية، تقدم Go نهجها الفريد في تنفيذ الأنماط من خلال الواجهات (interfaces) والتكوين (composition) والجوروتينات (goroutines). في هذه المقالة، سنشرح أنماط التصميم الأساسية في Go مع أمثلة كود محددة.
1. الأنماط الإنشائية (Creational Patterns)
الأنماط الإنشائية مسؤولة عن إنشاء الكائنات، مما يجعل النظام مستقلاً عن طريقة إنشائها.
1.1. Singleton (مفرد)
يضمن النمط المفرد أن يكون للفئة مثيل واحد فقط. في Go، يتم تنفيذ ذلك غالبًا باستخدام sync.Once لضمان أمان الخيوط.
package main
import ( "fmt" "sync")
type Database struct { connection string}
var ( instance *Database once sync.Once)
func GetDatabaseInstance() *Database { once.Do(func() { instance = &Database{connection: "postgres://localhost:5432/mydb"} fmt.Println("تم إنشاء اتصال واحد بقاعدة البيانات") }) return instance}
func main() { db1 := GetDatabaseInstance() db2 := GetDatabaseInstance() fmt.Println(db1 == db2) // true}1.2. Factory Method (طريقة المصنع)
يفوض نمط المصنع إنشاء الكائنات إلى الفئات الفرعية. في Go، يتم ذلك باستخدام الواجهات.
package main
import "fmt"
// واجهة المنتجtype Transport interface { Deliver() string}
// منتجات محددةtype Truck struct{}func (t Truck) Deliver() string { return "توصيل بري" }
type Ship struct{}func (s Ship) Deliver() string { return "توصيل بحري" }
// المصنعtype LogisticsFactory interface { CreateTransport() Transport}
type RoadLogistics struct{}func (r RoadLogistics) CreateTransport() Transport { return Truck{} }
type SeaLogistics struct{}func (s SeaLogistics) CreateTransport() Transport { return Ship{} }
func main() { var factory LogisticsFactory = RoadLogistics{} transport := factory.CreateTransport() fmt.Println(transport.Deliver()) // توصيل بري}2. الأنماط الهيكلية (Structural Patterns)
تساعد الأنماط الهيكلية في تنظيم الفئات والكائنات في هياكل أكبر.
2.1. Adapter (المهايئ)
يسمح المهايئ للكائنات ذات الواجهات غير المتوافقة بالعمل معًا. في Go، يتم حل ذلك من خلال التغليف.
package main
import "fmt"
// الواجهة القديمةtype OldPrinter interface { PrintOld(data string)}
type LegacyPrinter struct{}func (l LegacyPrinter) PrintOld(data string) { fmt.Println("Legacy:", data)}
// الواجهة الجديدةtype NewPrinter interface { PrintNew(data string)}
// المهايئtype PrinterAdapter struct { OldPrinter OldPrinter}
func (a PrinterAdapter) PrintNew(data string) { a.OldPrinter.PrintOld(data)}
func main() { legacy := LegacyPrinter{} adapter := PrinterAdapter{OldPrinter: legacy} adapter.PrintNew("Hello, Go!") // Legacy: Hello, Go!}2.2. Composite (المركب)
يسمح المركب بمعالجة مجموعات الكائنات ككائن واحد. مثالي للهياكل الشجرية.
package main
import "fmt"
// واجهة المكونtype Graphic interface { Draw() string}
// عنصر طرفيtype Circle struct{}func (c Circle) Draw() string { return "نرسم دائرة" }
// حاويةtype CompoundGraphic struct { children []Graphic}
func (cg *CompoundGraphic) Add(g Graphic) { cg.children = append(cg.children, g)}
func (cg *CompoundGraphic) Draw() string { result := "شكل مركب:" for _, child := range cg.children { result += " - " + c