شرح Composite Design Pattern بالتفصيل مع مثال توضيحي ومعرفة العيوب والمميزات
يُعد Composite Design Pattern أحد أنماط التصميم الهيكلية (Structural Design Patterns) في البرمجة الموجهة للكائنات (OOP)، ويُستخدم عندما نحتاج إلى التعامل مع الكائنات الفردية والكائنات المركبة بنفس الطريقة دون التمييز بينهما.
يسمح هذا النمط ببناء هيكل شجري (Tree Structure) يمكن من خلاله تمثيل العلاقات الهرمية، بحيث يتم التعامل مع العناصر البسيطة والمجموعات المعقدة باستخدام واجهة موحدة، مما يقلل التعقيد ويسهل الصيانة والتوسعة.
في هذه المقالة سنقدم شرح Composite Design Pattern بشكل عملي، مع مثال تطبيقي باستخدام Java في نظام دفع إلكتروني، مع مقارنة واضحة بين استخدام النمط وعدم استخدامه، واستعراض المميزات والعيوب.
ما هو Composite Design Pattern؟
بالتالي، لا يحتاج العميل لمعرفة ما إذا كان يتعامل مع عنصر فردي أو مجموعة عناصر، فجميعها تُعالج بنفس الطريقة.
مثال على استخدام Composite Design Pattern
باستخدام Composite Design Pattern، يمكننا التعامل مع المعاملة الفردية والمعاملة المجمعة بنفس الأسلوب دون كتابة منطق خاص لكل حالة.
كود جافا بدون استخدام Composite Design Pattern
class PaymentProcessor {
public void processCreditCardPayment() {
System.out.println("Processing Credit Card Payment...");
}
public void processPayPalPayment() {
System.out.println("Processing PayPal Payment...");
}
public void processCashPayment() {
System.out.println("Processing Cash Payment...");
}
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor();
processor.processCreditCardPayment();
processor.processPayPalPayment();
processor.processCashPayment();
}
}
عيوب هذا النهج بدون Composite Design Pattern
- صعوبة التوسع: إضافة طرق دفع جديدة أو دمج دفعات متعددة يتطلب تعديل الكود الحالي.
- إعادة استخدام محدودة: لا يمكن التعامل مع مجموعة من المدفوعات كوحدة واحدة.
- انتهاك مبدأ OCP: الكود مفتوح للتعديل في كل مرة يتم فيها إضافة وظيفة جديدة.
كود جافا باستخدام Composite Design Pattern
import java.util.ArrayList;
import java.util.List;
// واجهة الدفع الموحدة
interface PaymentComponent {
void processPayment();
}
// معاملة دفع فردية (Leaf)
class SinglePayment implements PaymentComponent {
private String paymentType;
public SinglePayment(String paymentType) {
this.paymentType = paymentType;
}
@Override
public void processPayment() {
System.out.println("Processing " + paymentType + " payment.");
}
}
// مجموعة مدفوعات (Composite)
class PaymentGroup implements PaymentComponent {
private List payments = new ArrayList<>();
public void addPayment(PaymentComponent payment) {
payments.add(payment);
}
public void removePayment(PaymentComponent payment) {
payments.remove(payment);
}
@Override
public void processPayment() {
for (PaymentComponent payment : payments) {
payment.processPayment();
}
}
}
// الاستخدام
public class Main {
public static void main(String[] args) {
PaymentComponent creditCard = new SinglePayment("Credit Card");
PaymentComponent payPal = new SinglePayment("PayPal");
PaymentComponent cash = new SinglePayment("Cash");
PaymentGroup paymentGroup = new PaymentGroup();
paymentGroup.addPayment(creditCard);
paymentGroup.addPayment(payPal);
paymentGroup.addPayment(cash);
paymentGroup.processPayment();
}
}
الفرق بين الطريقتين
- تعقيد مرتفع في الشيفرة البرمجية.
- صعوبة إضافة مجموعات أو طرق دفع جديدة.
- ضعف المرونة وإعادة الاستخدام.
- مرونة عالية في التعامل مع الكائنات.
- سهولة التوسعة دون تعديل الكود الحالي.
- إعادة استخدام عالية للكود.
مميزات Composite Design Pattern
- مرونة عالية: التعامل مع الكائنات الفردية والمركبة بنفس الطريقة.
- قابلية التوسعة: إضافة عناصر جديدة دون تعديل الكود الموجود.
- تقليل التعقيد: إزالة الحاجة إلى شروط متعددة.
- الالتزام بمبدأ OCP: مغلق للتعديل ومفتوح للإضافة.
عيوب Composite Design Pattern
- التعقيد المبدئي: قد يكون صعب الفهم في المشاريع الصغيرة.
- الأداء: بنية الشجرة قد تؤدي لاستهلاك موارد إضافية.
- زيادة عدد الكائنات: خاصة في الهياكل الكبيرة.
الخلاصة
يمكن تشبيهه أيضًا بالهيكل العسكري؛ حيث يصدر القائد الأوامر إلى من تحته، وكل مستوى يقوم بتنفيذ نفس التعليمات دون تضارب أو تشتت في القرارات.
على الرغم من التعقيد الأولي، فإن Composite Design Pattern يُعد خيارًا ممتازًا في المشاريع الكبيرة والمعقدة التي تتطلب مرونة عالية وقابلية توسعة وتنظيم قوي للشيفرة البرمجية.



