شرح State Design Pattern بالتفصيل مع مثال عملي في Java
إذا كنت تعاني من كثرة الشروط (if / else) في الكود وتبحث عن طريقة لتنظيم منطق الحالات بشكل احترافي، فإن State Design Pattern هو الحل المثالي.
يُعتبر هذا النمط من أهم أنماط التصميم السلوكية (Behavioral Design Patterns)، حيث يساعدك على تغيير سلوك الكائن بشكل ديناميكي بناءً على حالته الداخلية.
في هذا المقال ستتعلم مفهوم النمط، كيفية استخدامه، مع مثال عملي في Java، بالإضافة إلى مميزاته وعيوبه وأفضل الحالات لاستخدامه.
ما هو State Design Pattern؟
بدلاً من استخدام شروط معقدة مثل if و switch، يتم تقسيم كل حالة إلى كلاس مستقل يحتوي على السلوك الخاص بها.
هذا النمط يعتمد على مبدأ Encapsulation وPolymorphism، مما يجعل الكود أكثر تنظيمًا وقابلية للصيانة.
فكرة النمط بطريقة بسيطة
– Pending (قيد المعالجة) – Paid (تم الدفع) – Cancelled (ملغي)
كل حالة لها سلوك مختلف، وهنا يأتي دور State Design Pattern لتنظيم هذا السلوك بطريقة نظيفة.
مثال بدون استخدام State Design Pattern
public class Order {
private String state;
public Order() {
this.state = "Pending";
}
public void pay() {
if ("Pending".equals(state)) {
state = "Paid";
System.out.println("Order paid.");
} else if ("Paid".equals(state)) {
System.out.println("Order is already paid.");
} else if ("Cancelled".equals(state)) {
System.out.println("Cannot pay for a cancelled order.");
}
}
public void cancel() {
if ("Pending".equals(state)) {
state = "Cancelled";
System.out.println("Order cancelled.");
} else if ("Paid".equals(state)) {
System.out.println("Cannot cancel a paid order.");
} else if ("Cancelled".equals(state)) {
System.out.println("Order is already cancelled.");
}
}
}
مشاكل الطريقة التقليدية
مثال باستخدام State Design Pattern
interface OrderState {
void pay(OrderContext context);
void cancel(OrderContext context);
}
class PendingState implements OrderState {
public void pay(OrderContext context) {
context.setState(new PaidState());
System.out.println("Order paid.");
}
public void cancel(OrderContext context) {
context.setState(new CancelledState());
System.out.println("Order cancelled.");
}
}
class PaidState implements OrderState {
public void pay(OrderContext context) {
System.out.println("Order is already paid.");
}
public void cancel(OrderContext context) {
System.out.println("Cannot cancel a paid order.");
}
}
class CancelledState implements OrderState {
public void pay(OrderContext context) {
System.out.println("Cannot pay for a cancelled order.");
}
public void cancel(OrderContext context) {
System.out.println("Order is already cancelled.");
}
}
class OrderContext {
private OrderState state;
public OrderContext() {
this.state = new PendingState();
}
public void setState(OrderState state) {
this.state = state;
}
public void pay() {
state.pay(this);
}
public void cancel() {
state.cancel(this);
}
}
شرح كيف يعمل State Design Pattern
بهذا الشكل يتم التخلص من التعقيد الناتج عن الشروط المتداخلة.
الفرق بين الطريقتين
State Pattern يجعل الكود منظمًا وواضحًا.
المرونة
يمكن تغيير السلوك بسهولة بدون تعديل الكود الأساسي.
قابلية التوسع
يمكن إضافة حالات جديدة بسهولة.
مميزات State Design Pattern
يقلل من استخدام if/else بشكل كبير.
كود نظيف (Clean Code)
كل حالة في كلاس منفصل.
سهولة التوسع
إضافة حالات جديدة بدون كسر النظام.
مرونة عالية
تغيير السلوك أثناء التشغيل (Runtime).
عيوب State Design Pattern
كل حالة تحتاج كلاس منفصل.
تعقيد إضافي
قد يكون مبالغًا فيه في المشاريع الصغيرة.
زيادة حجم المشروع
بسبب تعدد الكلاسات.
متى تستخدم State Design Pattern؟
أفضل استخدامات النمط
الخلاصة
بدلاً من كتابة شروط معقدة، يمكنك تقسيم كل حالة إلى كلاس مستقل، مما يجعل الكود أكثر وضوحًا وقابلية للصيانة.
ورغم أنه يزيد عدد الكلاسات، إلا أنه يوفر مرونة كبيرة خاصة في المشاريع الكبيرة.
ببساطة: إذا وجدت نفسك تكتب الكثير من if/else، فغالبًا أنت بحاجة لاستخدام هذا النمط.
هذا النمط هو الحل المثالي لتحويل كود معقد إلى كود نظيف وسهل التطوير.
لمزيد من المقالات : أسباب مشكلة Hot Reload في Flutter ولماذا لا يعمل؟ الدليل الشامل للحل



