الگوی طراحی نرم افزار Factory Method یک الگوی طراحی creational است که یک رابط برای ایجاد اشیاء در یک سوپرکلاس فراهم میکند، اما به کلاسهای فرعی اجازه میدهد تا نوع اشیایی که ایجاد میشوند را تغییر دهند.
تصور کنید که در حال ایجاد یک برنامه مدیریت حمل و نقل هستید. اولین نسخه برنامه شما فقط می تواند حمل و نقل با کامیون را انجام دهد، بنابراین بخش عمده کد شما در کلاس Truck قرار دارد.
پس از مدتی، برنامه شما بسیار محبوب می شود. هر روز دهها درخواست از شرکت های حمل و نقل دریایی برای گنجاندن حمل و نقل دریایی در برنامه دریافت می کنید.
چه خبرهای خوبی، درست است؟ اما در مورد کد چطور؟ در حال حاضر، بیشتر کد شما به کلاس Truck چسبیده است. افزودن Ships به برنامه مستلزم ایجاد تغییراتی در کل code-base است. علاوه بر این، اگر بعداً تصمیم گرفتید نوع دیگری از حمل و نقل( مثلا حمل و نقل هوایی) را به برنامه اضافه کنید، احتمالاً باید همه این تغییرات را دوباره انجام دهید.
در نتیجه، کد بسیار بدی خواهید داشت که مملو از شرایطی است که رفتار برنامه را بسته به کلاس اشیاء حملونقل تغییر میدهد.
راه حل
الگوی Factory Method پیشنهاد میکند که تماسهای ساخت مستقیم شی (با استفاده از اپراتور new) را با فراخوانی factory method جایگزین کنید. نگران نباشید: اشیاء هنوز از طریق اپراتور new ایجاد می شوند، اما این کار از طریق factory method اتفاق میافتد. اشیایی که با این متد بازگردانده می شوند اغلب به عنوان Product شناخته می شوند.
در نگاه اول، این تغییر ممکن است بی معنی به نظر برسد: ما فقط ایجاد اشیا را از یک قسمت برنامه به قسمت دیگر منتقل کردیم. با این حال، این را در نظر بگیرید: اکنون می توانید متد ایجاد شی(factory method) مربوط به کلاس کارخانه(والد) را در زیر کلاسها(فرزندان) بازنویسی(override) کنید و از طرف دیگر کلاس محصولات ایجاد شده توسط این متد را تغییر دهید.
با این حال، یک محدودیت جزئی وجود دارد: کلاسهای فرزندان تنها در صورتی میتوانند انواع مختلف محصولات را برگردانند که این محصولات دارای یک کلاس پایه یا رابط مشترک باشند. همچنین factory method در کلاس پایه( متد createTransport در کلاس Logistics در تصویر بالا) باید نوع بازگشتی خود را به این رابط تغییر دهد.
برای مثال، هر دو کلاس Truck و Ship باید رابط Transport را پیاده سازی کنند، که متدی به نام deliver را الزام می کند. هر کلاس این روش را متفاوت پیاده سازی می کند: کامیون ها محموله را از طریق زمینی، کشتی ها محموله را از طریق دریا تحویل می دهند. factory method در کلاس RoadLogistics اشیاء کامیون را برمی گرداند، در حالی که factory method در کلاس SeaLogistics کشتی ها را برمی گرداند.
کدی که از factory Method استفاده می کند (اغلب کد مشتری نامیده می شود) تفاوتی بین محصولات واقعی بازگردانده شده توسط زیر کلاس های مختلف نمی بیند. مشتری با تمام محصولات به عنوان حمل و نقل انتزاعی رفتار می کند. مشتری می داند که قرار است همه اشیاء حمل و نقل دارای روش تحویل باشند، اما نحوه عملکرد دقیق آن برای مشتری مهم نیست.
ساختار الگوی طراحی نرم افزار Factory Method
۱- محصول رابط را اعلام می کند که برای همه اشیایی که می توانند توسط سازنده و زیر کلاس های آن تولید شوند مشترک است.
۲- منظور از ConcreteProduct پیاده سازی های مختلف رابط محصول هستند. مانند Ship و Truck در مثال این آموزش.
۳- کلاس Creator متد کارخانه ای را اعلام می کند که اشیاء محصول جدید را برمی گرداند. مهم است که نوع بازگشت این روش با رابط محصول مطابقت داشته باشد.
میتوانید متد کارخانه را بهعنوان انتزاعی اعلام کنید تا همه زیر کلاسها مجبور شوند نسخههای خود را از متد پیادهسازی کنند. به عنوان یک جایگزین، روش کارخانه پایه می تواند برخی از انواع محصولات پیش فرض را برگرداند.
توجه داشته باشید، با وجود نام آن، ایجاد محصول مسئولیت اصلی سازنده نیست. معمولاً، کلاس سازنده از قبل دارای منطق تجاری اصلی مرتبط با محصولات است. روش کارخانه کمک می کند تا این منطق از کلاس های محصولات بتنی جدا شود. در اینجا یک قیاس وجود دارد: یک شرکت بزرگ توسعه نرم افزار می تواند یک بخش آموزشی برای برنامه نویسان داشته باشد. با این حال، وظیفه اصلی شرکت به عنوان یک کل هنوز هم نوشتن کد است، نه تولید برنامه نویس.
۴- Concrete Creators روش کارخانه پایه را نادیده می گیرد بنابراین نوع متفاوتی از محصول را برمی گرداند. توجه داشته باشید که روش کارخانه مجبور نیست همیشه نمونههای جدیدی ایجاد کند. همچنین می تواند اشیاء موجود را از یک کش، یک مخزن آبجکت یا منبع دیگری برگرداند.
کاربرد الگوی طراحی نرم افزار Factory Method
زمانی از روش Factory استفاده کنید که از قبل انواع و وابستگی های دقیق اشیایی که کد شما باید با آنها کار کند را نمی دانید. Factory Method کد ساخت محصول را از کدی که در واقع از محصول استفاده می کند جدا می کند. بنابراین، گسترش کد ساخت محصول به طور مستقل از بقیه کد آسان تر است. به عنوان مثال، برای افزودن یک نوع محصول جدید به برنامه، فقط باید یک زیر کلاس سازنده جدید ایجاد کنید و متد سازنده را در آن override کنید.