3.7. State¶
3.7.1. تعریف¶
دیزاین پترن State یک الگوی رفتاری محسوب میشه که به آبجکت اجازه میده رفتارش رو با توجه به وضعیت یا State داخلیش تغییر بده.
الگوی State یک لیست از کلاس ها رو تعریف می کنه که نشان دهنده ی وضعیت های مختلفی هستن که یک کلاس میتونه داشته باشه و همچنین یک Context کلاس داریم که به آبجکت وضعیت فعلی یک اشاره گر داره.
3.7.2. چه زمانی استفاده میشه؟¶
این الگو زمانی مورد استفاده قرار میگیره که آبجکتی داریم که با توجه به وضعیت فعلیش رفتار های مختلفی از خودش نشون میده.
مثلا Cursor موس رو در نظر بگیرید که وقتی روی لینک ها قرار میگیره شکل و عملکردش عوض میشه!
3.7.3. اجزاء¶
الگوی طراحی State از چند بخش اصلی تشکیل میشه:
بخش اول این الگو Context نام داره که نگهدارنده ی state object هست و با توجه به وضعیت فعلی، رفتارش عوض میشه.
مورد بعد State هست که یک Interface برای پیاده سازی های State ها محسوب میشه.
و در نهایت هم پیاده سازی های State ها رو داریم که مشخص کننده ی رفتار آبجکت در وضعیت های مختلف هستن.
State_Design_Pattern_UML_Class_Diagram.png: JoaoTrindade (talk)The original uploader was JoaoTrindade at English Wikipedia.derivative work: Ertwroc, CC BY-SA 3.0, via Wikimedia Commons
Caution
✅ مزایای استفاده
نگهداری بهتر و ساده تر کد با جداسازی هر وضعیت -> اصل Open/Closed
جداسازی رفتار یک آبجکت از وضعیت آن -> اصل تک مسئولیتی
رفتار داینامیک: امکان تغییر رفتار آبجکت در زمان اجرا که باعث میشه حتی انعطاف پذیری بیشتری هم در برنامه بوجود بیاد
Warning
❌ معایب استفاده
استفاده از اون در زمانی که فقط چند state محدود برای یک آبجکت داریم، اضافه کاری محسوب میشه و فقط کد رو پیچیده می کنه
3.7.4. کاربرد عملی¶
این الگو در PHP نسبتا کاربرد متوسطی داره و معمولا برای تبدیل State Machine های بزرگ به آبجکت ها استفاده میشه.
فرض کنید یک ادیتور داریم که متنی که در اون تایپ میشه میتونه حالات مختلفی داشته باشه.
این قابلیت از ادیتور رو میتونیم با استفاده از الگوی State پیاده سازی کنیم.
3.7.5. پیاده سازی¶
قبل از هر چیز Interface مربوط به State ها رو به این صورت داریم:
1<?php
2
3/**
4 * The WritingStateInterface defines the interface for all writing states.
5 */
6interface WritingStateInterface
7{
8 public function write(string $words);
9}
بعد میریم سراغ انواع State هایی که میتونیم داشته باشیم:
1<?php
2
3/**
4 * The UpperCase class represents a writing state where all text is converted to uppercase.
5 */
6class UpperCase implements WritingStateInterface
7{
8 public function write(string $words)
9 {
10 echo strtoupper($words) . "\n";
11 }
12}
13
14/**
15 * The LowerCase class represents a writing state where all text is converted to lowercase.
16 */
17class LowerCase implements WritingStateInterface
18{
19 public function write(string $words)
20 {
21 echo strtolower($words) . "\n";
22 }
23}
24
25/**
26 * The DefaultText class represents the default writing state where text is output as is.
27 */
28class DefaultText implements WritingStateInterface
29{
30 public function write(string $words)
31 {
32 echo $words . "\n";
33 }
34}
و بعد هم TextEditor رو داریم:
1<?php
2
3/**
4 * The TextEditor class maintains a reference to a writing state and allows changing it at runtime.
5 */
6class TextEditor
7{
8 private WritingStateInterface $state;
9
10 public function __construct()
11 {
12 $this->state = new DefaultText();
13 }
14
15 public function setState(WritingStateInterface $state): void
16 {
17 $this->state = $state;
18 }
19
20 public function type(string $words): void
21 {
22 $this->state->write($words);
23 }
24}
3.7.6. نحوه فراخوانی¶
1<?php
2
3// Example usage
4$editor = new TextEditor();
5
6$editor->type("First line");
7
8$editor->setState(new UpperCase());
9
10$editor->type("Second Line");
11$editor->type("Third Line");
12
13$editor->setState(new LowerCase());
14
15$editor->type("Fourth Line");
16$editor->type("Fifth Line");
17
18// Output:
19// First line
20// SECOND LINE
21// THIRD LINE
22// fourth line
23// fifth line
به راحتی میشه State رو تغییر داد بدون اینکه Client از جزئیات نحوه پیاده سازی هر State خبر داشته باشه.