دیزاین پترن Factory Method

👈 خب این دیزاین پترن از نوع ایجادی هست و کارش مدیریت نمونه سازی از کلاس‌هاست.اما دقیقا چطور؟


👁 بازدید : 114

1403/2/7 | 23:30 : تاریخ 📆


دیزاین پترن‌ها راه حل‌های هستند برای حل مشکلات رایج در طراحی نرم افزار و به با کمک میکنن تا یک برنامه خوانا و قابل توسعه داشته باشیم.در این مقاله میخواییم به توضیح دیزاین پترن Factory Method بپردازیم تا یک دید کامل ازش بدست بیاریم.

خب این دیزاین پترن از نوع ایجادی هست و کارش مدیریت نمونه سازی از کلاس‌هاست.اما دقیقا چطور؟

بیایید توی این موضوع رو با یک مثال بررسی و با کد پیاده سازیش کنیم:

فرض کنید که یک برنامه مدیریت لجستیک دارید. اولین نسخه برنامه شما فقط می تونه حمل و نقل با کامیون را انجام بده، بنابراین بخش عمده کد شما در کلاس Truck قرار میگیره.مدتی بعد، شما درخواست‌هایی دریافت میکنید از شرکت های حمل و نقل دریایی برای گنجاندن تدارکات دریایی در برنامه‌تون.اما مشکل اینجاست که کدهای شما با کلاس Truck پیاده سازی شده و جایی برای انعطاف پذیری کد برای کلاس Ship وجود نداره، در نتیجه کار شما برای توسعه سخت میشه.حالا برای دسترسی به متدهای هر کلاس باید از روی کلاس نمونه سازی کنی اما Factory Method اینو نقض میکنه میگه شما حق نداری بارها و هرجا دلت خواست از روی کلاس نمونه سازی کنی. حالا Factory Method یک پیشنهاد به ما میده. میگه به جای اینکه هی بیای نمونه سازی کنی یک کلاس abstract درست کن متدهایی که لازم داری رو بنویس و یک متد abstract درست کن برای مدیریت نمونه سازی‌ها.

بیایید کدهاشم یه نگاه بندازیم:

اول یک اینترفیس برای رفتار سازی:

public interface ITransport
{
    void Deliver();
}

کلاس Truck:

public class Truck : ITransport
{
    public void Deliver()
    {
        Console.WriteLine("We Will Transfer Your Product By Truck From Road");
    }
}

کلاس Ship:

 public class Ship:ITransport
 {
     public void Deliver()
     {
         Console.WriteLine("We Will Transfer Your Product By Ship From Sea");
     }
 }

و کلاس Logistic برای مدیریت نحوه ارسال:

public abstract class Logistics
{

    public abstract ITransport CreateTransport();
    
}

چون ITransport اینترفیس پایه برای کلاس Truck و کلاس Ship هست و نحوه Deliver مشخص میکنه متد abstract ما با اون ساخته میشه.

حالا لازمه به ازای هر نوع حمل و نقل(مثلا دریایی یا زمینی) یک کلاس بسازیم و مشخص کنیم با کامیون یا کشتی محصول ارسال بشه.

کلاس RoadLogistic :

public class RoadLogistic : Logistics
{
    public override ITransport CreateTransport()
    {
       return new Truck();
    }
}

کلاس SeaLogistic:

 public class SeaLogistic: Logistics
 {
     public override ITransport CreateTransport()
     {
         return new Ship();
     }
 }

حالا تو هرجایی که خواستیم خروجی بگیریم یا کدهامون کار کنه(مثلا داخل یک کلاس) یک متد از جنس ITransport  میسازیم و پارامتر ورودیشو کلاس Logistics در نظر میگیریم از این به بعد ایشون و متدش CreateTransport هستن که وظیفه نمونه سازی رو برعهده دارن.

static ITransport Client(Logistics logistics)
{
    return logistics.CreateTransport();
}

من چون در محیط کنسول کد نوشتم میرم در بدنه Main و کار اصلیمو میگم:

var roadLogistic = Client(new RoadLogistic());
roadLogistic.Deliver();

var seaLogistic = Client(new SeaLogistic());
seaLogistic .Deliver();

و خروجی :

We Will Transfer Your Product By Truck From Road
We Will Transfer Your Product By Ship From Sea

یکبار هم کل کدهای کلاس Program.cs رو براتون مینویسم:

internal class Program
{
    static void Main(string[] args)
    {
        var roadLogistic = Client(new RoadLogistic());
        roadLogistic.Deliver();

        var seaLogistic  = Client(new SeaLogistic());
        seaLogistic .Deliver();

        Console.ReadKey();
    }

    static ITransport Client(Logistics logistics)
    {
        return logistics.CreateTransport();
    }
}

نتیجه گیری :

همینطور که از اسم این الگو پیداس ما داریم یک متد میسازیم که درواقع تولید کننده و مدیریت کننده نمونه سازی هاست و کدهای ما رو خواناتر منعطف تر و قابل توسعه در  مقیاس‌های بزرگتر میکنه.امیدوارم این مقاله براتون مفید بوده باشه. اما در آخر ازتون یک سوال مهم دارم و یک چالش بزرگ در این الگو. 

اگر ما یک حمل و نقل جاده دیگه مثلا قطار اضافه کنیم اونوقت چطور باید نمونه سازی از کلاس Truck و Train رو مدیریت کنیم!؟

 منبع : refactoring.guru

دیزاین پترن‌ها راه حل‌های هستند برای حل مشکلات رایج در طراحی نرم افزار و به با کمک میکنن تا یک برنامه خوانا و قابل توسعه داشته باشیم.در این مقاله میخواییم به توضیح دیزاین پترن Factory Method بپردازیم تا یک دید کامل ازش بدست بیاریم.

خب این دیزاین پترن از نوع ایجادی هست و کارش مدیریت نمونه سازی از کلاس‌هاست.اما دقیقا چطور؟

بیایید توی این موضوع رو با یک مثال بررسی و با کد پیاده سازیش کنیم:

فرض کنید که یک برنامه مدیریت لجستیک دارید. اولین نسخه برنامه شما فقط می تونه حمل و نقل با کامیون را انجام بده، بنابراین بخش عمده کد شما در کلاس Truck قرار میگیره.مدتی بعد، شما درخواست‌هایی دریافت میکنید از شرکت های حمل و نقل دریایی برای گنجاندن تدارکات دریایی در برنامه‌تون.اما مشکل اینجاست که کدهای شما با کلاس Truck پیاده سازی شده و جایی برای انعطاف پذیری کد برای کلاس Ship وجود نداره، در نتیجه کار شما برای توسعه سخت میشه.حالا برای دسترسی به متدهای هر کلاس باید از روی کلاس نمونه سازی کنی اما Factory Method اینو نقض میکنه میگه شما حق نداری بارها و هرجا دلت خواست از روی کلاس نمونه سازی کنی. حالا Factory Method یک پیشنهاد به ما میده. میگه به جای اینکه هی بیای نمونه سازی کنی یک کلاس abstract درست کن متدهایی که لازم داری رو بنویس و یک متد abstract درست کن برای مدیریت نمونه سازی‌ها.

بیایید کدهاشم یه نگاه بندازیم:

اول یک اینترفیس برای رفتار سازی:

public interface ITransport
{
    void Deliver();
}

کلاس Truck:

public class Truck : ITransport
{
    public void Deliver()
    {
        Console.WriteLine("We Will Transfer Your Product By Truck From Road");
    }
}

کلاس Ship:

 public class Ship:ITransport
 {
     public void Deliver()
     {
         Console.WriteLine("We Will Transfer Your Product By Ship From Sea");
     }
 }

و کلاس Logistic برای مدیریت نحوه ارسال:

public abstract class Logistics
{

    public abstract ITransport CreateTransport();
    
}

چون ITransport اینترفیس پایه برای کلاس Truck و کلاس Ship هست و نحوه Deliver مشخص میکنه متد abstract ما با اون ساخته میشه.

حالا لازمه به ازای هر نوع حمل و نقل(مثلا دریایی یا زمینی) یک کلاس بسازیم و مشخص کنیم با کامیون یا کشتی محصول ارسال بشه.

کلاس RoadLogistic :

public class RoadLogistic : Logistics
{
    public override ITransport CreateTransport()
    {
       return new Truck();
    }
}

کلاس SeaLogistic:

 public class SeaLogistic: Logistics
 {
     public override ITransport CreateTransport()
     {
         return new Ship();
     }
 }

حالا تو هرجایی که خواستیم خروجی بگیریم یا کدهامون کار کنه(مثلا داخل یک کلاس) یک متد از جنس ITransport  میسازیم و پارامتر ورودیشو کلاس Logistics در نظر میگیریم از این به بعد ایشون و متدش CreateTransport هستن که وظیفه نمونه سازی رو برعهده دارن.

static ITransport Client(Logistics logistics)
{
    return logistics.CreateTransport();
}

من چون در محیط کنسول کد نوشتم میرم در بدنه Main و کار اصلیمو میگم:

var roadLogistic = Client(new RoadLogistic());
roadLogistic.Deliver();

var seaLogistic = Client(new SeaLogistic());
seaLogistic .Deliver();

و خروجی :

We Will Transfer Your Product By Truck From Road
We Will Transfer Your Product By Ship From Sea

یکبار هم کل کدهای کلاس Program.cs رو براتون مینویسم:

internal class Program
{
    static void Main(string[] args)
    {
        var roadLogistic = Client(new RoadLogistic());
        roadLogistic.Deliver();

        var seaLogistic  = Client(new SeaLogistic());
        seaLogistic .Deliver();

        Console.ReadKey();
    }

    static ITransport Client(Logistics logistics)
    {
        return logistics.CreateTransport();
    }
}

نتیجه گیری :

همینطور که از اسم این الگو پیداس ما داریم یک متد میسازیم که درواقع تولید کننده و مدیریت کننده نمونه سازی هاست و کدهای ما رو خواناتر منعطف تر و قابل توسعه در  مقیاس‌های بزرگتر میکنه.امیدوارم این مقاله براتون مفید بوده باشه. اما در آخر ازتون یک سوال مهم دارم و یک چالش بزرگ در این الگو. 

اگر ما یک حمل و نقل جاده دیگه مثلا قطار اضافه کنیم اونوقت چطور باید نمونه سازی از کلاس Truck و Train رو مدیریت کنیم!؟

 منبع : refactoring.guru

🗨️دیدگاه‌ها


دیزاین پترن Factory Method

هنوز دیدگاهی ثبت نشده

تمامی‌حقوق‌مادی‌ومعنوی‌این‌سایت‌برای‌یادمیگیریم‌محفوظ است.