الگوی Abstract Factory

برای فهم بهتر Abstract Factory شما نیاز دارید تا درک درستی از دلیل پیدایش این الگو ها و همچنین مزایای استفاده از آنها داشته باشید.شما می‌توانید با مراجعه به بخش اول (الگوهای طراحی نرم افزار - Design Patterns)، پیشنیاز این آموزش را مطالعه نمایید.هدف (Intent)Abstract Factory یکی از الگوهای خلاقانه (Creational)، که امکان ایجاد خانواده‌ای از Object ها، با ویژگی مشترک را به شما می‌دهد.بیان مسئلهفرض کنید شما یک نرم افزار فروش میز و صندلی برای یک شرکت طراحی کردید. مشتریان دائم به دنبال محصولات جدید و مدل های متفاوت هستند و از طرفی شرکت های ارایه دهنده این نوع محصولات، به دنبال به روز کردن کاتالوگ مطابق با نیاز مشتری می باشند. شما باید ساختار کد را به شکلی طراحی کنید، که به ازای ارائه مدل های متفاوت هر محصول، نیازی به تغییرات بنیادی در سیستم نباشید. ? راه حلدر این الگو یک Interface مسئول ایجاد خانواده ای از Object ها، بدون نیاز به اشاره مستقیم به کلاس آنها می باشد.این الگو به شما پیشنهاد می‌کند که یک Interface از Object های اصلی (distinct) ایجاد کنید. سپس دیگر Object های هم خانواده را از این رابط بسازید.بعد از این مرحله به یک کلاس abstract با نام Abstract Factory نیازمندیم که شامل توابع مختلفی برای ایجاد Object ها و هم خانواده های آن می‌باشد.تمام توابع در کلاس Abstract Factory باید به صورت abstract تعریف شوند.در قدم دوم یک کلاس Abstract ایجاد کنید که شامل توابع ساخت هر محصول باشد.و در پایان شما به ازای هر محصول یک کلاس Factory نیاز دارید تا محصولات متنوع را بسازید.ساختاریمثال کاربردی در Abstract Factoryدر مثال زیر ما قصد داریم علاوه بر ایجاد اشکال مختلف، از هر شکل مدل های متفاوتی نیز ایجاد کنیم. ? ابتدا Interface متناسب با Object های اصلی را ایجاد می‌کنیم. تا بوسیله آن بتوانیم هم خانواده های آن را نیز تولید کنیم.interface Shape { public function draw(); }interface RoundedShape { public function draw(); }بعد از ایجاد Interface نیاز داریم تا Object های مختلف را طبق با آن یسازیم.class Rectangle implements Shape { public function draw(){ echo &quotRectangle&quot } }class RoundedRectangle implements RoundedShape { public function draw() { echo &quotRoundedRectangle&quot } }class Square implements Shape { public function draw(){ echo &quotSquare&quot } }class RoundedSquare implements RoundedShape { public function draw() { echo &quotRoundedSquare&quot } }حالا یک کلاس Abstract Factory ایجاد می‌کنیم و توابع مورد نیاز برای ایجاد Object را به آن اضافه می‌کنیم.abstract class AbstractFactory { abstract function getShape(); abstract function getRoundedShape(); }در این مرحله نیاز است تا کلاس Factory برای ایجاد Object‌های یک خانواده را ایجاد کنیم.class RectangleFactory extends AbstractFactory { public function getShape() { return new Rectangle(); } public function getRoundedShape() { return new RoundedRectangle(); } }class SquareFactory extends AbstractFactory { public function getShape() { return new Square(); } public function getRoundedShape() { return new RoundedSquare(); } }در پایان از ساختاری که ایجاد کردیم در کلاینت خود (بخشی که الگو از آن استفاده می‌کند) استفاده می کنیم.function client(AbstractFactory $abstractFactory){ $getShape = $abstractFactory->getShape(); $getRoundedShape = $abstractFactory->getRoundedShape(); $getShape->draw(); $getRoundedShape->draw(); } client(new RectangleFactory()); // Rectangle // RoundedRectangle client(new SquareFactory()); // Square // RoundedSquareمزایاشما را از ایجاد Object هایی با ویژگی یکسان مطمئن می‌کند.از ایجاد وابستگی (coupling) بین کلاس سازنده Object و کلاینت جلوگیری می‌کند.شما می‌توانید کد ایجاد Object را در یک ماژول جدا قرار دهید و در تمام پروژه از آن استفاده کنید.به عبارتی دیگر اصل قابل نگهداری بودن (Maintainable) نرم افزار را نیز رعایت کنید.شما می‌توانید Object های مختلفی بدون تغییر در ساختار اصلی کد ایجاد کنید.معایبممکن است پیچیدگی زیادی در پیاده سازی کد ایجاد شود ، زیرا شما نیاز دارید به ازای هر Object یک کلاس Factory و Interface بسازید.