حوزه: Class
هدف: Creational
نقش الگو
این الگو پیچیدگی ایجاد اشیاء برای استفاده کننده را پنهان میکند. ما با این الگو میتوانیم بدون اینکه کلاس دقیق یک شیئ را مشخص کنیم آن را ایجاد و از آن استفاده کنیم. کلاینت ( استفاده کننده ) معمولا شیئ واقعی را ایجاد نمیکند بلکه با یک واسط و یا کلاس انتزاعی (Abstract) در ارتباط است و کل مسئولیت ایجاد کلاس واقعی را به Factory Method میسپارد. کلاس Factory Method میتواند استاتیک باشد . کلاینت معمولا اطلاعاتی را به متدی استاتیک از این کلاس میفرستد و این متد بر اساس آن اطلاعات تصمیم میگیرید که کدام یک از پیاده سازیها را برای کلاینت برگرداند. الگوی Factory Method راهی برای ساخت اشیا میباشد و برای تولید اشیا از کلاس ها مورد استفاده قرار میگیرد. اما تفاوتی که وجود دارد این است که این الگو به زیرکلاس ها (subclass) اجازه میدهد که از کلاسی که مورد نظرشان است شی را بسازد. زیرکلاسهای متفاوت ممکن است که پیاده سازیهای متفاوتی داشته باشند. الگوی Factory Method با توجه به اطلاعات کاربر از آن زیرکلاسی که مدنظر است شیئی را میسازد.
از مزایای این الگو این است که اگر در نحوه ایجاد اشیاء تغییری رخ دهد هیچ نیازی به تغییر در کد کلاینتها نخواهد بود. در این الگو اصل DIP از اصول پنجگانه SOLID به خوبی رعایت میشود چون که مسئولیت ایجاد زیرکلاسها از دوش کلاینت برداشته میشود.
شرح الگو
اگر یک میوه فروشی موجود باشد که در کل روزهای سال میوه آوکادو میفروشد. این میوه فروشی باید مطمئن باشد که میتواند در طول سال این میوه را از کشاورزان تهیه نماید. این میوه فروشی باید از نواحی و کشورهای مختلف این میوه را در طول سال خریده و در داخل فروشگاه عرضه نماید. این میوه در کشورهای اسپانیا، آفریقای جنوبی و کنیان در فصلهای متفاوتی رشد میکند. الگوی Factory Method شبیه به این میوه فروشی عمل میکند.
طراحی الگو
طراحی این الگو به این شکل است که کاربر یک متغیر Product معرفی میکند و از Factory Method میخواهد که آن را مقدار دهی نماید. شیئی که ساخته میشود به این بستگی دارد که چه تصمیمی برای ساخت شی product گرفته شده است. نمودار uml این الگو به شکل زیر است. دقت کنید که در این نمودار دو نوع product به نامهای productA و productB وجود دارد.
عناصری که در این نمودار وجود دارند به شرح زیر هستند:
IProduct: اینترفیسی برای کلاس Product
productA, productB: کلاس هایی که اینترفیس IProduct را پیاده سازی میکنند.
Creator کلاسی که الگوی Factory Method را میسازد.
Factory Method تصمیم میگیرد که از کدام کلاس شی ساخته شود.
طراحی این الگو باعث میشود که بتوانیم در مورد این که کدام شی ساخته شود در یک زمان تصمیم گیری کنیم. نیازی نیست که کاربر بداند که زیرکلاس های مختلف را چگونه استفاده کند و فقط از اشیا ساخته شده استفاده میکند.
پیاده سازی، مثال: فراهم کردن میوه آوکادو
اگر بخواهیم برای این الگو یک مثال بیاوریم همان فراهم کردن میوه آوکادو را پیاده سازی میکنیم. اگر هرکدام از کشورهای تولید کننده آوکادو را به عنوان یک کلاس در نظر بگیریم و هرکدام اینترفیس IProduct را پیاده سازی میکند. بنابراین این کشورها میتوانند آوکادو برای میوه فروشی فراهم کنند. کشورهای تولید کننده آوکادو با توجه به این که در کدام ماه از سال قرار داشته باشیم انتخاب میشوند. کد پیاده سازی و نتیجه آن به این شکل است.
public class FactoryPattern {
interface IProduct {
String ShipFrom();
}
static class ProductA implements IProduct {
public String ShipFrom() {
return "from South Africa";
}
}
static class ProductB implements IProduct {
public String ShipFrom() {
return "from Spain";
}
}
static class DefaultProduct implements IProduct {
public String ShipFrom() {
return "not available";
}
}
static class Creator {
public IProduct FactoryMethod(int month) {
if (month >= 4 && month <= 11)
return new ProductA();
else if (month == 1 || month == 2 || month == 12)
return new ProductB();
else return new DefaultProduct();
}
}
public static void main(String[] args) {
Creator creator = new Creator();
IProduct product;
for (int i = 1; i <= 12; i++) {
product = creator.FactoryMethod(i);
System.out.println("Avocados " + product.ShipFrom());
}
}
}
و نتیجه اجرای برنامه به شکل زیر خواهد شد.
Avocados from Spain
Avocados from Spain
Avocados not available
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from South Africa
Avocados from Spain
همانگونه که در کد دیده میشود، ما در متد main فقط از creator استفاده کردهایم که این creator به اقتضای زمان تصمیم میگیرد که از کدام کلاس استفاده کند و هر کدام از کلاس ها یک متد ShipFrom دارند که آن را با توجه به نیاز خود پیاده سازی کرده اند.
موارد استفاده
از این الگو در موارد زیر استفاده میشود.
- زمانی که در برنامه ما انعطاف پذیری مهم باشد.
- اشیا بتوانند در زیرکلاس ها گسترش پیدا کنند.
- دلیل مشخصی وجود دارد که یک زیرکلاس به زیرکلاس دیگر ارجحیت دارد. این منطق قسمتی از الگوی FactoryMethod است.
مثال پیاده سازی شده با زبان جاوا را میتوانید از github من دانلود کنید.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.