1. ما هو نمط الوكيل (Proxy Pattern)
نمط الوكيل (Proxy Pattern) هو نمط تصميم هيكلي يعمل كوكيل للسيطرة على الوصول إلى كائن معين. بناءً على الكائن المستهدف (الكائن القيد)، يوفر نمط الوكيل (Proxy Pattern) كائن وكيل من خلاله يمكن للعملاء الوصول إلى الكائن المستهدف، مما يسمح بإضافة وظائف إضافية إلى الكائن المستهدف.
1.1 تعريف نمط الوكيل (Proxy Pattern)
نمط الوكيل (Proxy Pattern) هو نمط تصميم يشمل تعاون أثنين أو أكثر من الكائنات. يكون أحد الكائنات الفعلي هو الكائن المستهدف الذي يتم استدعاؤه، بينما يعمل كائن أو أكثر ككائنات وكيل. يقوم كائنات الوكيل بالتقاط الوصول إلى الكائن المستهدف، مما يوفر وسيلة غير مباشرة للوصول إلى الكائن المستهدف.
1.2 الغرض والأهداف من نمط الوكيل (Proxy Pattern)
الغرض الرئيسي من نمط الوكيل (Proxy Pattern) هو توفير وسيلة غير مباشرة للوصول إلى الكائن المستهدف، مما يسمح بإضافة وظائف إضافية إلى الكائن المستهدف. يمكن لكائنات الوكيل التعامل مع المنطق الشائع، مثل التحكم في الوصول إلى الكائن المستهدف، والتخزين المؤقت، والتسجيل. كما يمكن لنمط الوكيل (Proxy Pattern) تنفيذ التحميل الكسلي، حيث يتم إنشاء الكائن المستهدف فقط عند الحاجة إليه.
2. سمات ومزايا نمط الوكيل (Proxy Pattern)
نمط الوكيل (Proxy Pattern) له السمات والمزايا التالية:
- يمكنه توسيع وظائف الكائن المستهدف دون تعديله.
- يمكنه التحكم في الوصول إلى الكائن المستهدف من خلال كائن الوكيل.
- يمكنه أداء عمليات إضافية قبل أو بعد الوصول إلى الكائن المستهدف.
- يمكنه تنفيذ التحميل الكسلي، حيث يتم إنشاء الكائن المستهدف فقط عند الحاجة إليه.
3. أمثلة لتطبيقات نمط الوكيل (Proxy Pattern)
يُستخدم نمط الوكيل (Proxy Pattern) على نطاق واسع في العديد من سيناريوهات التطبيق. فيما يلي بعض الأمثلة الشائعة للتطبيقات العملية:
- الوكيل البعيد (Remote Proxy): يُستخدم للوصول إلى الكائنات على الشبكة محليًا.
- الوكيل الافتراضي (Virtual Proxy): يُستخدم لإنشاء كائنات مكلفة حسب الحاجة.
- الوكيل الأماني (Security Proxy): يُستخدم للتحكم في الوصول إلى الكائنات.
- المرجع الذكي (Smart Reference): يُستخدم لأداء عمليات إضافية عند الوصول إلى الكائنات، مثل عد الكائنات.
4.1 رسم الفئة UML
الآتي هو رسم الفئة UML لنمط الوكيل (Proxy Pattern) في Golang:
4.2 مقدمة المثال
لنفترض أن لدينا واجهة Subject
التي تحدد طريقة Request
. لدينا فئة تنفيذ محددة RealSubject
، التي تنفذ واجهة Subject
. ثم نقوم بإنشاء فئة وكيل Proxy
، التي تحتوي على كائن RealSubject
وتنفذ أيضًا واجهة Subject
. في طريقة Request
لفئة Proxy
، يمكننا أداء عمليات إضافية قبل أو بعد استدعاء طريقة Request
في RealSubject
.
4.3 تنفيذ الخطوة 1: تحديد واجهة الوكيل
أولاً، نحتاج إلى تحديد واجهة Subject
التي تحتوي على طريقة Request
:
package main
type Subject interface {
Request()
}
4.4 تنفيذ الخطوة 2: تنفيذ الكائن المستهدف
ثم نقوم بتنفيذ الكائن المستهدف المحدد RealSubject
، الذي ينفذ واجهة Subject
:
package main
import "fmt"
type RealSubject struct {}
func (r *RealSubject) Request() {
fmt.Println("RealSubject: Handling Request")
}
4.5 تنفيذ الخطوة 3: تنفيذ الكائن الوكيل
ثم نقوم بإنشاء كائن الوكيل، Proxy، الذي يحتوي على كائن RealSubject وينفذ واجهة Subject. في طريقة Request الخاصة بالوكيل، يمكننا أداء بعض العمليات الإضافية قبل أو بعد استدعاء طريقة Request في RealSubject:
package main
import "fmt"
type Proxy struct {
realSubject *RealSubject
}
func (p *Proxy) Request() {
fmt.Println("Proxy: Pre-Request")
if p.realSubject == nil {
p.realSubject = &RealSubject{}
}
p.realSubject.Request()
fmt.Println("Proxy: Post-Request")
}
4.6 تنفيذ الخطوة 4: استدعاء كائن الوكيل
أخيرًا، يمكننا استخدام كائن الوكيل، Proxy، لاستدعاء طرق الكائن المُوكَّل، RealSubject:
package main
func main() {
proxy := Proxy{}
proxy.Request()
}
تشغيل الكود أعلاه سينتج عنه المخرجات:
Proxy: Pre-Request
RealSubject: Handling Request
Proxy: Post-Request
5.1 الفرق والاتصال بين نمط الوكيل ونمط المزين
كلاً من نمط الوكيل ونمط المزين هما أنماط تصميم هيكلية، كلتاهما تحتوي على كائن الهدف وكائن الوكيل/المزين. ومع ذلك، هناك بعض الاختلافات بين الاثنين:
- يُشمل نمط الوكيل عادةً التحكم في الوصول إلى كائن الهدف، بينما يركز نمط المزين أكثر على توسيع كائن الهدف.
- يُؤدي نمط الوكيل عادةً عمليات إضافية قبل أو بعد كائن الهدف، في حين يضيف نمط المزين بشكل ديناميكي وظائف إضافية على كائن الهدف.
5.2 المقارنة بين الوكيل الثابت والوكيل الدينامي
يمكن تقسيم نمط الوكيل إلى وكيل ثابت ووكيل دينامي. يُحدد الوكيل الثابت نوع كائن الوكيل عند وقت الإنشاء، ويتم كتابة كائن الوكيل يدويًا من قبل المبرمج. بينما يولد الوكيل الدينامي كائن الوكيل بشكل دينامي خلال تشغيل البرنامج بناءً على واجهة كائن الهدف. الوكيل الدينامي أكثر مرونة ولكنه أكثر تعقيدًا مقارنة بالوكيل الثابت.
5.3 تطبيق نمط الوكيل في الخدمات المصغرة
يمكن تطبيق نمط الوكيل في هندسة النظم المصغرة. على سبيل المثال، يمكننا استخدام وكيلاً لتغليف الوصول إلى خدمات مصغرة أخرى وتنفيذ آليات مثل توازن الحمل وتحديد معدل الوصول وكسر الدائرة على طبقة الوكيل. يمكن أن يعزز هذا الأمان وأداء النظام. كما يمكن استخدام نمط الوكيل أيضًا لتنفيذ اكتشاف الخدمات ووظائف التوجيه.