الگوهای ساخت درباره یک پرسشاند: چه کسی تصمیم میگیرد کدام کلاس ساخته شود. اگر جوابش «همانجا که استفاده میشود» باشد، هر جای تازهای که استفاده کند باید همان تصمیم را دوباره بگیرد.
سادهترین و پرکاربردترین شکلش در پایتون یک دیکشنری است که کلاسها را نگه میدارد، نه نمونهها:
KHANANDE = {".csv": CsvReader, ".json": JsonReader}def khanande_baraye(nam):pasvand = os.path.splitext(nam)[1]return KHANANDE[pasvand]()
صدا زدنش با نام foroush.csv یک نمونه CsvReader تحویل میدهد. کلاس در پایتون خودش یک مقدار است، پس میشود در یک دیکشنری گذاشتش و بعدا صدایش زد، و همین است که کل زنجیره شرط را حذف میکند. اضافه کردن یک قالب تازه یک سطر در دیکشنری است و نه یک شاخه تازه در تابع. حالت ناشناخته را صریح جواب دهید، وگرنه KeyError با یک پیام بیمعنی برای کاربر بالا میآید: تبدیلش کنید به خطایی که نام پسوند در آن باشد، مثل khanande baraye .xlsx nist. همان بند from None هم زنجیره را تمیز نگه میدارد و خطای داخلی دیکشنری را در گزارش نمیآورد.
سه شکل دیگر، و کاری که هرکدام حل میکنند
سازندهای که آرگومانهای زیاد و اختیاری دارد، جایش متد کلاسی است: Faktor.az_radif(satr) و Faktor.az_json(payload) دو راه ساختاند که هر دو همان کلاس را برمیگردانند و نامشان میگوید ورودی از کجا آمده. این ارزانترین الگوی این صفحه است و بیشترین استفاده را دارد.
شیای که ساختنش گران است و باید یکی باشد، در پایتون معمولا نه با کلاس تکنمونهای بلکه با یک ماژول حل میشود، چون ماژول یک بار وارد میشود و همان یک بار بس است؛ یا با functools.cache روی تابع سازنده. و وقتی ساختن یک شی چند مرحله دارد که ترتیبشان مهم است، الگوی سازنده تدریجی یعنی یک شی جدا که مرحلهها را جمع میکند و در پایان یک بار میسازد.
و جایی که هیچکدام لازم نیست
اگر فقط یک کلاس دارید، CsvReader() درستترین کد ممکن است و هر لایهای رویش فقط خواندن را سخت میکند. این الگوها وقتی خرجشان درمیآید که تعداد پیادهسازیها بیش از یکی باشد و انتخاب میانشان به داده وابسته باشد. اصلی که همین را با نام میگوید در پنج اصل، و اینکه هرکدام جلوی چه چیزی را میگیرد است.
جایی که کار گیر میکند، ترجمه مستقیم از جاواست
بیشتر منابع فارسی این الگوها را از کتابهای جاوا برمیدارند و کد نمونهشان همان کلاس انتزاعی کارخانه با چند فرزند است. در پایتون آن ساختار تقریبا هیچوقت لازم نیست، چون کلاس خودش مقدار است و تابع هم مقدار است. نتیجهای که آدم میگیرد این است که الگوهای طراحی یعنی کد زیاد، و بعد کلا کنارشان میگذارد. ایده همان است و پیادهسازیاش در پایتون سه سطر است، و همان سه سطر دقیقا همان چیزی است که در آن کتابها چهار کلاس میخواست.
ابزار، و سالی که این حرف درست است
در سال ۲۰۲۶، functools.cache در کتابخانه استاندارد و رایگان است و جای کلاس تکنمونهای با متغیر سراسری را میگیرد؛ روی یک تابع بدون آرگومان، همان یک شی را برای همیشه برمیگرداند و هیچ کلاسی لازم ندارد. برای ساختن نمونه از داده خام، dataclasses در همان کتابخانه سازنده را خودش مینویسد و متد کلاسی شما فقط تبدیل ورودی را انجام میدهد. هیچکدام بسته بیرونی نیستند.
پرسش بعدی این است که وقتی شی ساخته شد و باید رفتارش را بدون عوض کردن کلاسش تغییر دهید چه کار میکنید، که ترکیب شیها در شکلهای بزرگتر جوابش را دارد. و اگر مسئله این است که چند شی باید به هم خبر بدهند، اینکه شیها چطور با هم حرف میزنند دسته دیگری است.