مدیریت عملیات آسنکرون در سازندههای #C: الگوی متد کارخانه آسنکرون (Async Factory Method)
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۳/۰۸ ۰۸:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
Spy داریم که اطلاعات اولیه یک جاسوس را نگهداری میکند:public sealed class Spy
{
public string FirstName { get; }
public string Surname { get; }
public Spy(string firstName, string surname)
{
FirstName = firstName;
Surname = surname;
}
}FirstName و Surname را تنظیم میکند. حال، فرض کنید میخواهیم هنگام ساخت یک شیء Spy، یک موسیقی متن نیز به صورت آسنکرون پخش شود. برای این منظور، متد PlaySong را به صورت زیر تعریف میکنیم:// Play theme song here
public async Task PlaySong()
{
await Task.Delay(TimeSpan.FromSeconds(5)); // شبیهسازی یک عملیات زمانبر
Console.WriteLine("Playing that song!");
}async و await، یک عملیات آسنکرون را شبیهسازی میکند که ۵ ثانیه طول میکشد.PlaySong را مستقیماً از درون سازنده فراخوانی و await کنیم، با خطا مواجه خواهیم شد:public Spy(string firstName, string surname)
{
FirstName = firstName;
Surname = surname;
await PlaySong(); // این خط باعث بروز خطا میشود
}error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'. error CS4008: Cannot await 'void'.
Task<T> نیست، که این نوع بازگشتی برای متدهای async الزامی است. سازنده باید به طور همزمان (synchronously) شیء را برگرداند.private تغییر میدهیم تا از ایجاد مستقیم نمونه کلاس از خارج آن جلوگیری شود. این کار تضمین میکند که تنها راه ایجاد شیء، از طریق متد کارخانه خواهد بود.public static async Task ایجاد میکنیم. این متد وظیفه ایجاد نمونه و انجام عملیات آسنکرون مورد نیاز برای مقداردهی اولیه را بر عهده خواهد داشت.Spy، کد به شکل زیر تغییر میکند:public sealed class Spy
{
public string FirstName { get; }
public string Surname { get; }
// 1. سازنده به private تغییر یافته است
private Spy(string firstName, string surname)
{
FirstName = firstName;
Surname = surname;
}
// متد آسنکرون برای پخش موسیقی
public async Task PlaySong()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Console.WriteLine("Playing that song!");
}
/// <summary>
/// Factory method to return a spy
/// </summary>
/// <param name="firstName"></param>
/// <param name="surname"></param>
/// <returns>یک Task که نتیجه آن شیء Spy کاملاً مقداردهی شده است</returns>
// 2. متد کارخانه ایستا و آسنکرون
public static async Task<Spy> CreateSpy(string firstName, string surname)
{
// فراخوانی سازنده خصوصی برای ایجاد نمونه اولیه شیء
var spy = new Spy(firstName, surname);
// فراخوانی و انتظار برای تکمیل متد آسنکرون
await spy.PlaySong();
// بازگرداندن شیء کاملاً مقداردهی شده
return spy;
}
}private Spy): این سازنده دیگر از خارج کلاس قابل فراخوانی نیست و تنها توسط متد کارخانه (CreateSpy) استفاده میشود. این سازنده همچنان وظیفه مقداردهی اولیه همزمان (synchronous) فیلدهای اصلی را بر عهده دارد.CreateSpy):static است، بنابراین میتوان آن را بدون نیاز به ایجاد نمونهای از کلاس Spy فراخوانی کرد (مثلاً Spy.CreateSpy(...)).async است و نوع بازگشتی آن Task میباشد. این بدین معناست که متد، یک "وعده" (promise) برای تحویل یک شیء Spy در آینده را برمیگرداند.Spy با استفاده از سازنده خصوصی ایجاد میشود (var spy = new Spy(firstName, surname);).PlaySong بر روی این نمونه فراخوانی شده و با استفاده از await، اجرای متد کارخانه تا زمان تکمیل PlaySong متوقف میشود (await spy.PlaySong();).spy بازگردانده میشود.Spy با استفاده از این الگو، کد زیر را به کار میبریم:// Create the spy asynchronously
var jamesBond = await Spy.CreateSpy("James", "Bond");
// Use the spy
Console.WriteLine($"Spy was created: {jamesBond.FirstName} {jamesBond.Surname}");Playing that song! Spy was created: James Bond
jamesBond به طور کامل انجام شده است.async را نمیدهد، اما این محدودیت به معنای عدم امکان انجام عملیات آسنکرون در طول فرآیند مقداردهی اولیه اشیاء نیست. الگوی متد کارخانه آسنکرون، با خصوصی کردن سازنده و معرفی یک متد ایستا و آسنکرون برای ایجاد و آمادهسازی شیء، یک راهحل قدرتمند، تمیز و استاندارد برای این چالش ارائه میدهد. این رویکرد به توسعهدهندگان داتنت امکان میدهد تا برنامههایی بنویسند که هم از قدرت برنامهنویسی آسنکرون بهرهمند شوند و هم ساختار کد خود را منظم و قابل فهم نگه دارند. با استفاده صحیح از این الگو، میتوان اشیائی را ایجاد کرد که قبل از استفاده، به طور کامل و صحیح، حتی با وابستگی به عملیات آسنکرون، مقداردهی اولیه شدهاند.