وضعیت (State)
هـــدف
حالت یک الگوی طراحی رفتاری است که به یک شیء اجازه میدهد رفتار خود را هنگام تغییر حالت داخلی خود تغییر دهد. به نظر میرسد که شیء کلاس خود را تغییر داده است.
مـسئـــلـه
الگوی وضعیت، ارتباط نزدیکی با مفهوم ماشین حالت محدود دارد.
ماشین حالت محدود
ایده اصلی این است که در هر لحظه، تعداد محدودی از حالتهایی وجود دارد که یک برنامه میتواند در آنها باشد. در هر حالت منحصر به فرد، برنامه رفتار متفاوتی دارد و برنامه میتواند به طور آنی از یک حالت به حالت دیگر تغییر کند. با این حال، بسته به حالت فعلی، برنامه ممکن است یا ممکن است به حالتهای خاص دیگری تغییر نکند. این قوانین سوئیچینگ، که انتقال نامیده میشوند، نیز محدود و از پیش تعیین شده هستند.
همچنین میتوانید این رویکرد را به اشیاء اعمال کنید. تصور کنید که ما یک کلاس سند داریم. یک سند میتواند در یکی از سه حالت پیشنویس، تعدیل و منتشر شده باشد. متد انتشار سند کمی متفاوت در هر حالت عمل میکند:
در پیشنویس، سند را به تعدیل منتقل میکند.
در تعدیل، سند را عمومی میکند، اما فقط اگر کاربر فعلی یک مدیر باشد.
در منتشر شده، هیچ کاری انجام نمیدهد.
حالتهای ممکن و انتقالهای یک شیء سند
ماشینهای حالت معمولاً با تعداد زیادی عبارت شرطی (if یا switch) پیادهسازی میشوند که رفتار مناسب را بسته به حالت فعلی شیء انتخاب میکنند. معمولاً، این “حالت” فقط مجموعهای از مقادیر فیلدهای شیء است. حتی اگر قبلاً در مورد ماشینهای حالت محدود چیزی نشنیده باشید، احتمالاً حداقل یک بار یک حالت را پیادهسازی کردهاید. آیا ساختار کد زیر زنگ را به صدا در میآورد؟
class Document is
field state: string
// ...
method publish() is
switch (state)
"draft":
state = "moderation"
break
"moderation":
if (currentUser.role == "admin")
state = "published"
break
"published":
// Do nothing.
break
// ...
بزرگترین ضعف یک ماشین حالت مبتنی بر شرطها زمانی آشکار میشود که شروع به افزودن حالتها و رفتارهای وابسته به حالت بیشتر و بیشتر به کلاس سند کنیم. اکثر متدها شامل شرطهای عظیمی خواهند بود که رفتار مناسب یک متد را بر اساس حالت فعلی انتخاب میکنند. چنین کدی بسیار دشوار برای نگهداری است زیرا هر تغییری در منطق انتقال ممکن است نیاز به تغییر شرایط حالت در هر متد داشته باشد.
مشکل با تکامل یک پروژه بزرگتر میشود. پیشبینی تمام حالتها و انتقالهای ممکن در مرحله طراحی بسیار دشوار است. بنابراین، یک ماشین حالت لاغر ساخته شده با مجموعهای محدود از شرطها میتواند با گذشت زمان به یک آشفتگی متورم تبدیل شود.
راهــکــــار
الگوی حالت پیشنهاد میکند که برای همه حالتهای ممکن یک شیء کلاسهای جدید ایجاد کنید و تمام رفتارهای وابسته به حالت را به این کلاسها استخراج کنید.
به جای پیادهسازی تمام رفتارها به تنهایی، شیء اصلی، که زمینه نامیده میشود، مرجعی به یکی از اشیاء حالت ذخیره میکند که حالت فعلی آن را نشان میدهد و تمام کارهای مرتبط با حالت را به آن شیء واگذار میکند.
برای انتقال زمینه به حالت دیگر، شیء حالت فعال را با شیء دیگری که آن حالت جدید را نشان میدهد جایگزین کنید. این فقط در صورتی امکانپذیر است که همه کلاسهای حالت یک رابط مشترک را دنبال کنند و خود زمینه از طریق آن رابط با این اشیاء کار کند.
این ساختار ممکن است شبیه به الگوی استراتژی باشد، اما یک تفاوت کلیدی وجود دارد. در الگوی حالت، حالتهای خاص ممکن است از یکدیگر آگاه باشند و انتقال از یک حالت به حالت دیگر را آغاز کنند، در حالی که استراتژیها تقریباً هرگز یکدیگر را نمیشناسند.
مقایسه با دنیای واقعی
دکمهها و سوئیچها در گوشی هوشمند شما بسته به حالت فعلی دستگاه رفتار متفاوتی دارند:
هنگامی که گوشی قفل نشده است، فشار دادن دکمهها منجر به اجرای عملکردهای مختلف میشود.
هنگامی که گوشی قفل است، فشار دادن هر دکمهای منجر به صفحه قفل میشود.
هنگامی که شارژ گوشی کم است، فشار دادن هر دکمهای صفحه شارژ را نشان میدهد.
ســاخــتـــار
برای مطـالعـه متن کامل مقالــه، مجموعه کــــدها، نحوه پیاده سازی، مزایا و معایب و روابط با الگوهای دیگر، ایــنــجـــا کلیک کنید.