الگوی طراحی Factory Method
به همراه مثال
عناوین :
·
تعریف Factory Method
·
دیاگرام UML
·
شرکت
کنندگان در UML
·
مثالی از Factory Pattern در #C
تعریف الگوی Factory Method :
این الگو پیچیدگی ایجاد اشیاء برای استفاده کننده را پنهان میکند. ما با این الگو میتوانیم بدون اینکه کلاس دقیق یک شیئ را مشخص کنیم آن را ایجاد و از آن استفاده کنیم. کلاینت ( استفاده کننده ) معمولا شیئ واقعی را ایجاد نمیکند بلکه با یک واسط و یا کلاس انتزاعی (Abstract) در ارتباط است و کل مسئولیت ایجاد کلاس واقعی را به Factory Method میسپارد. کلاس Factory Method میتواند استاتیک باشد . کلاینت معمولا اطلاعاتی را به متدی استاتیک از این کلاس میفرستد و این متد بر اساس آن اطلاعات تصمیم میگیرید که کدام یک از پیاده سازیها را برای کلاینت برگرداند.
از مزایای این الگو این است که اگر در نحوه ایجاد اشیاء تغییری رخ دهد هیچ نیازی به تغییر در کد کلاینتها نخواهد بود. در این الگو اصل DIP از اصول پنجگانه SOLID به خوبی رعایت میشود چون که مسئولیت ایجاد زیرکلاسها از دوش کلاینت برداشته میشود.
دیاگرام UML :
در شکل زیر دیاگرام UML الگوی
Factory Method را مشاهده میکنید.
شرکت کنندگان در این
الگو به شرح زیل هستند :
- Iproduct یک واسط است که هر کلاینت از آن استفاده میکند. در اینجا کلاینت استفاده کننده نهایی است مثلا میتواند متد main یا هر متدی در کلاسی خارج از این
الگو باشد. ما میتوانیم پیاده سازیهای مختلفی بر حسب نیاز از واسط Iproduct ایجاد کنیم.
- ConcreteProduct یک پیاده سازی از واسط Iproduct است ، برای این کار بایستی کلاس پیاده سازی (ConcreteProduct) از این واسط (IProduct) مشتق شود.
- Icreator واسطیست که Factory Method را تعریف میکند. پیاده ساز این
واسط بر اساس اطلاعاتی دریافتی کلاس صحیح را ایجاد میکند. این اطلاعات از طریق پارامتر
برایش ارسال میشوند.همانطور که گفتیم این عملیات بر عهده پیاده ساز این واسط است
و ما در این نمودار این وظیفه را فقط بر عهده ConcreteCreator گذاشته ایم که از واسط Icreator مشتق شده است.
پیاده سازی UMLفوق به صورت زیر است:
در ابتدا کلاس واسط IProduct تعریف شده است.
interface IProduct
{
// در اینجا برحسب نیاز فیلدها و یا امضای متدها قرار میگیرند
}
در این مرحله ما پند پیاده سازی از IProduct انجام میدهیم.
class ConcreteProductA : IProduct
{
// A پیاده سازی
}
class ConcreteProductB : IProduct
{
// B پیاده سازی
}
در این مرحله کلاس انتزاعی Creator تعریف میشود.
abstract class Creator
{
// این متد بر اساس نوع ورودی انتخاب مناسب را انجام و باز میگرداند
public abstract IProduct FactoryMethod(string type);
}
در این مرحله ما با ارث بری از Creator متد Abstract آن را به شیوه خودمان پیاده سازی میکنیم.
class ConcreteCreator : Creator
{
public override IProduct FactoryMethod(string type)
{
switch (type)
{
case "A": return new ConcreteProductA();
case "B": return new ConcreteProductB();
default: throw new ArgumentException("Invalid type", "type");
}
}
}
مثالی از Factory Pattern در #C : برای روشنتر شدن موضوع ، یک مثال کاملتر ارائه داده میشود. در شکل زیر طراحی این برنامه نشان داده شده است.
کد برنامه به شرح زیل است :
using System;
namespace FactoryMethodPatternRealWordConsolApp
{
internal class Program
{
private static void Main(string[] args)
{
VehicleFactory factory = new ConcreteVehicleFactory();
IFactory scooter = factory.GetVehicle("Scooter");
scooter.Drive(10);
IFactory bike = factory.GetVehicle("Bike");
bike.Drive(20);
Console.ReadKey();
}
}
public interface IFactory
{
void Drive(int miles);
}
public class Scooter : IFactory
{
public void Drive(int miles)
{
Console.WriteLine("Drive the Scooter : " + miles.ToString() + "km");
}
}
public class Bike : IFactory
{
public void Drive(int miles)
{
Console.WriteLine("Drive the Bike : " + miles.ToString() + "km");
}
}
public abstract class VehicleFactory
{
public abstract IFactory GetVehicle(string Vehicle);
}
public class ConcreteVehicleFactory : VehicleFactory
{
public override IFactory GetVehicle(string Vehicle)
{
switch (Vehicle)
{
case "Scooter":
return new Scooter();
case "Bike":
return new Bike();
default:
throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", Vehicle));
}
}
}
}
خروجی اجرای برنامه فوق به شکل زیر است :