استراتژی پترن درواقع نوعی از دیزاین پترنهای Behavioral است که به شما اجازه میدهد راهکارهایی که برنامهٔ مورد نظرتان باید اجرا کند، بسته به شرایط خاصی که در Runtime (یا هنگام اجرای برنامه) برایش رخ میدهد را انتخاب نمایید. شما 2 الگوریتم مختلف را داخل 2 کلاس جدا از یکدیگر بهاصطلاح Encapsulate میکنید و هنگام اجرای برنامه، انتخاب میشود که از کدام استراتژی استفاده کند.
فرض کنید مسئولیت ایجاد راهحلی برای ادغام 2 کلاس مختلف که 2 عملکرد کاملاً مجزا از یکدیگر دارند را به شما محول کردهاند؛ این ۲ کلاس در جاهای مختلفی در سیستم بهکار رفتهاند، بنابراین حذف این ۲ کلاس یا تغییر کدهای موجود را باید از سرتان بیرون کنید چراکه اصلاً کار سادهای نخواهد بود.
بهعلاوه، با تغییر کد فعلی، شما باید کدهای جدید را دوباره تست کنید چرا که این نوع تغییرات، در سیستمی که به کامپوننتهای مختلفی وابسته است، در اکثر مواقع باعث ایجاد باگهای جدیدی میشود. بهجای این کار، میتوانید نوعی از استراتژی پترن و آداپتر پترن را پیادهسازی نمایید که بهراحتی میتوانند این گونه مسائل را حلوفصل کنند:
class StrategyAndAdapterExampleClass {
private $_class_one;
private $_class_two;
private $_context;
public function __construct( $context ) {
$this->_context = $context;
}
public function operation1() {
if( $this->_context == "context_for_class_one" ) {
$this->_class_one->operation1_in_class_one_context();
} else ( $this->_context == "context_for_class_two" ) {
$this->_class_two->operation1_in_class_two_context();
}
}
}
همانطور که در کد فوق مشاهده میشود، متدی ساختهایم تحت عنوان operation1 که بسته به نوع پارامتر ورودی، نیاز ما را بهسادگی هندل میکند.
در مثال بالا، استراتژیی که مورد استفاده قرار میگیرد، طبق متغیر context$ای است که در زمان معرفی کلاس موردنظر ایجاد شده است. اگر شما کلاس اول را مدنظر قرار دهید، این متغییر نیز از class_one استفاده میکند و بالعکس.
در چه مواقعی میتوان از دیزاین پترن Strategy استفاده کنیم؟
فرض کنید شما کلاسی دارید که میتواند رکورد کاربر فعلی را آپدیت یا کاربر جدیدی را ایجاد نماید؛ این کلاس در هر ۲ حالت ورودی یکسانی را انتظار دارد از قبیل نام، آدرس، شمارهٔ همراه و غیره اما بسته به موقعیت مورد نظر، باید از فانکشنهای مختلفی برای بهروز رسانی یا ایجاد کاربر استفاده کند.
در سادهترین حالت، شما میتوانید از دستور شرطی if-else استفاده کنید اما اگر خواستید این کلاس را در جای دیگری به کار ببرید، چهطور؟ در این مواقع، شما باید همین if-else را در مکان جدید نیز بازنویسی کنید. اما آیا اگر امکان این فراهم شود که فقط نام کلاس را به کار ببرید و بقیه کار را به آن بسپارید راحتتر نخواهید بود؟
class User {
public function CreateOrUpdate($name, $address, $mobile, $userid = null)
{
if( is_null($userid) ) {
// it means the user doesn't exist yet, create a new record
} else {
// it means the user already exists, just update based on the given userid
}
}
}
استراتژی پترن در حالت عادی شامل کپسوله کردن الگوریتمها در کلاس دیگری میشود اما در این مورد، استفاده از کلاس دیگر بیفایده است. به خاطر داشته باشید که نیازی نیست همیشه از ساختار پیشفرض پیروی کنید. تا وقتی که مفهوم مورد نظر دیزاین پترن رعایت شده و مشکل حل شود، میتوانید طبق نیازتان دست به تغییر دیزاین پترن مد نظر بزنید.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید