تا کنون 23 الگوی طراحی برای رفع مشکلات متداول در برنامه نویسی شی گرا توسعه داده شده است که یکی از آنها الگوی طراحی کارخانه یا Factory Method است. الگوی طراحی کارخانه در دسته الگوهای طراحی سازنده یا Creational قرار دارد و به شما در مدیریت ایجاد اشیا کمک میکند. این الگوی طراحی، راهکاری در اختیار برنامه نویسان قرار میدهد تا آنها را قادر سازد که بدون اینکه کلاس دقیق یک شی را مشخص کنند آن را ایجاد کنند و به استفاده از آن بپردازند. در ادامه این مقاله با الگوی طراحی Factory Method آشنا خواهیم شد و خواهیم دید چه زمانی استفاده از این الگوی طراحی در کدنویسی به کمک ما خواهد آمد.
در بعضی موارد اپلیکیشنهای ما بسیار بزرگ و پیچیده هستند و یا در آینده گسترش خواهند یافت. معمولا این اپلیکیشنها دارای تعداد خیلی زیادی کلاس (Class) هستند که از همه آنها نمونه و شی (Object) ساخته میشود. تصور کنید که اپلیکیشن شما دارای 500 کلاس باشد که از هر کدام از آنها باید به صورت میانگین 10 شی و نمونه ساخته شود. بنابراین در نرم افزار حدود 5000 هزار شی از کلاسها مختلف ساخته شده است. مثلا کلاسی مثل User که در سرتاسر اپلیکیشن مورد استفاده قرار میگیرد.
بنابراین اگر مثلا بخواهیم به Constructor مربوط به کلاس User پارامتری جدید اضافه کنیم، باید کلاس User را تغییر دهیم. این کار باعث میشود که در تمام پروژه، هر جایی که از آن کلاس شی ای ساخته شده است پارامتر جدید را مقداردهی و اضافه کنیم که کاری بسیار دشوار و زمان بر خواهد بود. اما با استفاده از الگوی طراحی Factory برای ساخت اشیا کارخانه ای خواهیم ساخت که وظیفه ساخت اشیا از کلاسهای مختلف را بر عهده دارد. با این کار دیگر نیازی به ساخت شیها با استفاده از کیورد new به صورت جداگانه نخواهیم داشت و کافی است برای ساخت اشیا از کارخانه ساخت آن کلاس استفاده کنیم.
مثلا برای ساخت شیها و نمونه هایی از کلاس User از Userfactory استفاده میکنیم. با این کار اگر نیاز به اعمال تغییراتی در کلاس مورد نظر خود داشته باشیم، کافی است تغییرات در کارخانه یا Factory مربوط به آن کلاس اعمال کنیم. پس از این عمل، تغییرات اعمال شده توسط کارخانه بر تمام کلاسهای ساخته شده در آن، لحاظ میشوند.
تصور کنید که وظیفه طراحی نرم افزاری برای مدیریت حمل و نقل اجناس تولیدی یک کارخانه بر عهده شما باشد. اولین نسخه ای که از این نرم افزار میسازید فقط میتواند حمل و نقل جاده ای را مدیریت کند. بنابراین بخش عمده ای از کدهای نوشته شده توسط شما در کلاس کامیون (Truck) نوشته شده اند. سپس بعد از مدتی نرم افزاری که طراحی کرده اید مورد توجه کاربران و مدیران کارخانه قرار میگیرد و به این دلیل تعداد زیادی درخواست برای توسعه نرم افزار به منظور پشتیبانی از مدیریت حمل و نقل دریایی دریافت میکنید.
قطعا اولین سوالی که در ذهن شما شکل میگیرد مربوط به چگونگی پیاده سازی ویژگیهای جدید مربوط به حمل نقل دریایی است. زیرا در حال حاضر، بیشتر کد شما در کلاس مربوط به کامیونها وارد شده است. اگر بخواهید کشتیها (Ships) را به نرم افزار خود اضافه کنید، نیازمند تغییر در تمام کدهای اصلی نرم افزار خواهید بود. اگر در آینده دوباره تصمیم بگیرید نرم افزار را گسترش دهید، همچنین با این چالشها مواجه خواهید شد. اگر بخواهید این چالشها را به صورت سنتی حل کنید، نرم افزار شما انعطاف پذیر نخواهد بود و امکان دارد با مشکلات زیادی مواجه شود.
کاربرد این الگوی طراحی برای شرایطی است که چندین کلاس ما از یک کلاس دیگر ارث بری کرده باشند و معمولا از آن کلاس نمونه یا شی ساخته میشود. همچنین این الگوی طراحی در موارد دیگر هم نیز استفاده میشود. این موارد عبارتند از :
در این بخش به بررسی مراحل پیاده سازی الگوی طراحی Factory میپردازیم، سپس با استفاده از زبان برنامه نویسی PHP این الگو را در قالب یک مثال برای تولید ماشینهای سواری پژو 405 و سمند پیاده سازی خواهیم کرد. در این مثال با استفاده از الگوی طراحی کارخانه دیگر نیازی به تعیین ویژگیهای هر ماشین در زمان تولید آن به صورت تک به تک نخواهیم داشت. زیرا با ساخت کارخانه تولیدی ماشینهای سواری و مشخص کردن ویژگیهای هر یک از آن ها، وظیفه ساخت این خودروها بر عهده کارخانه خواهد بود. مراحل پیاده سازی این الگو عبارتند از :
<?php namespace Web7learn\FactoryMethod\CarFactory; /** * The CarFactory class declares the carfactory method that is supposed to return an * object of a Car class. The CarFactory's subclasses usually provide the * implementation of this method. */ abstract class CarFactory { /** * Note that the CarFactory may also provide some default implementation of the * carfactory method. */ abstract public function buildcar(): Car; /** * Also note that, despite its name, the CarFactory's primary responsibility is * not creating Cars. Usually, it contains some core business logic that * relies on car objects, returned by the buildcar method. Subclasses can * indirectly change that business logic by overriding the factory method * and returning a different type of Car from it. */ public function someOperation(): Type { //U can Call the buildCar method to create a car object and use that Here. } } /** * Concrete Car Factories override the factory method in order to change the * resulting car's type. */ class PeugeotFactory extends CarFactory { /** * Note that the signature of the method still uses the abstract Car * type, even though the concrete Car is actually returned from the * method. This way the CarFactory can stay independent of concrete Car * classes. */ public function buildcar(): Car { return new Peugeot405; } } class SamandFactory extends CarFactory { public function buildcar(): Car { return new Samand; } } /** * The Car interface declares the operations that all concrete Cars must * implement. */ interface Car { public function operation(): Type; } /** * Concrete Cars provide various implementations of the Car interface. */ class PeugeotFactory implements Car { public function operation(): Type { return "{Result of the Peugeot405}"; } } class SamandFactory implements Car { public function operation(): Type { return "{Result of the Samand}"; } }
پیاده سازی الگوی طراحی Factory برای نرم افزارهایی که امکان دارد در آینده گسترش یابند بسیار مفید است. پیاده سازی این الگوی طراحی در نرم افزارها به افزایش انعطاف آنها در برابر تغییرات بسیار کمک میکند. همچنین این الگو باعث بهینه سازی در مصرف منابع خواهد شد. نظر شما در مورد الگوی طراحی کارخانه چیست؟ آیا تاکنون از این الگوی طراحی در طراحی نرم افزارهای خود استفاده کرده اید؟