سـبک وزن (Fly Weight)
هـــدف
الگوی سبک وزن، یک الگوی طراحی ساختاری است که به شما امکان میدهد با اشتراکگذاری قسمتهای مشترک حالت بین چندین شیء به جای نگه داشتن تمام دادهها در هر شیء، تعداد بیشتری از اشیاء را در مقدار حافظه موجود جای دهید.
مـسئـــلـه
برای داشتن کمی سرگرمی بعد از ساعتهای طولانی کار، تصمیم گرفتید یک بازی ساده ایجاد کنید: بازیکنان در یک نقشه حرکت میکردند و به یکدیگر شلیک میکردند. شما تصمیم گرفتید یک سیستم ذرات واقعگرایانه پیادهسازی کنید و آن را به یک ویژگی متمایز بازی تبدیل کنید. مقادیر زیادی از گلوله، موشک و ترکش از انفجارها باید در سراسر نقشه پرواز کنند و یک تجربه هیجانانگیز برای بازیکن ایجاد کنند.
پس از تکمیل، آخرین کامیت را فشار دادید، بازی را ساختید و برای تست به دوست خود فرستادید. اگرچه بازی روی دستگاه شما بدون نقص اجرا میشد، اما دوست شما نتوانست برای مدت طولانی بازی کند. روی کامپیوتر او، بازی بعد از چند دقیقه بازی کردن خراب میشد. پس از چند ساعت بررسی لاگهای دیباگ، متوجه شدید که بازی به دلیل کمبود حافظه رم خراب شده است. مشخص شد که دستگاه دوست شما بسیار ضعیفتر از کامپیوتر شما بود و به همین دلیل مشکل خیلی زود در دستگاه او ظاهر شد.
مشکل واقعی مربوط به سیستم ذرات شما بود. هر ذره، مانند یک گلوله، موشک یا قطعه ترکش، توسط یک شیء جداگانه با دادههای فراوان نشان داده میشد. در برخی مواقع، زمانی که کشتار روی صفحه نمایش بازیکن به اوج خود میرسید، ذرات جدید ایجاد شده دیگر در رم باقیمانده جا نمیشدند، بنابراین برنامه خراب میشد.
راهــکــــار
با بررسی دقیقتر کلاس Particle، ممکن است متوجه شوید که فیلدهای رنگ و اسپرایت حافظه بسیار بیشتری نسبت به فیلدهای دیگر مصرف میکنند. بدتر از آن این است که این دو فیلد تقریباً دادههای یکسانی را در تمام ذرات ذخیره میکنند. به عنوان مثال، همه گلولهها رنگ و اسپرایت یکسانی دارند.
بیایید به بازی خود بازگردیم. با فرض اینکه حالت بیرونی را از کلاس ذره استخراج کردهایم، تنها سه شیء مختلف برای نمایش تمام ذرات در بازی کافی خواهد بود: یک گلوله، یک موشک و یک قطعه ترکش. همانطور که احتمالا حدس زدهاید، شیئی که فقط حالت ذاتی را ذخیره میکند، وزن سبک نامیده میشود.
ذخیره سازی حالت بیرونی
حالت بیرونی به کجا منتقل میشود؟ برخی کلاسها هنوز باید آن را ذخیره کنند، درست است؟ در بیشتر موارد، به شیء ظرف منتقل میشود که اشیاء را قبل از اعمال الگو جمعآوری میکند.
در مورد ما، این شیء اصلی بازی است که تمام ذرات را در فیلد ذرات ذخیره میکند. برای انتقال حالت بیرونی به این کلاس، باید چندین فیلد آرایهای برای ذخیره مختصات، بردارها و سرعت هر ذرهی فردی ایجاد کنید. اما این همه چیز نیست. شما به یک آرایه دیگر برای ذخیره مراجع به یک وزن سبک خاص که یک ذره را نشان میدهد نیاز دارید. این آرایهها باید همگام باشند تا بتوانید با استفاده از همان شاخص به تمام دادههای یک ذره دسترسی پیدا کنید.
یک راه حل ظریفتر ایجاد یک کلاس زمینه جداگانه است که حالت بیرونی را همراه با مرجع به شیء وزن سبک ذخیره میکند. این رویکرد نیاز به داشتن تنها یک آرایه در کلاس ظرف دارد.
صبر کنید! آیا به اندازه تعداد اشیاء اولیه به این اشیاء زمینه نیاز نخواهیم داشت؟ از نظر فنی، بله. اما نکته اینجاست که این اشیاء بسیار کوچکتر از قبل هستند. فیلدهای پرهزینه ترین حافظه به چند شیء وزن سبک منتقل شدهاند. اکنون، هزاران شیء زمینه کوچک میتوانند از یک شیء وزن سبک سنگین استفاده مجدد کنند، به جای ذخیره هزاران نسخه از دادههای آن.
وزن سبک و تغییر ناپذیری
از آنجایی که همان شیء وزن سبک میتواند در زمینههای مختلف استفاده شود، باید مطمئن شوید که حالت آن قابل تغییر نیست. یک وزن سبک باید حالت خود را فقط یک بار، از طریق پارامترهای سازنده، مقداردهی اولیه کند. نباید هیچگونه تنظیمکننده یا فیلد عمومی را برای اشیاء دیگر در معرض دید قرار دهد.
کـــارخـــانه وزن ســبـــک
برای دسترسی راحتتر به وزن سبکهای مختلف، میتوانید یک متد کارخانه ایجاد کنید که یک استخر از اشیاء وزن سبک موجود را مدیریت کند. این متد حالت ذاتی وزن سبک مورد نظر را از یک مشتری دریافت میکند، به دنبال یک شیء وزن سبک موجود با تطابق با این حالت میگردد و در صورت پیدا شدن آن را برمیگرداند. در غیر این صورت، یک وزن سبک جدید ایجاد میکند و آن را به استخر اضافه میکند.
چندین گزینه برای قرار دادن این متد وجود دارد. واضحترین مکان یک ظرف وزن سبک است. به طور جایگزین، میتوانید یک کلاس کارخانه جدید ایجاد کنید. یا میتوانید متد کارخانه را استاتیک کرده و آن را داخل یک کلاس وزن سبک واقعی قرار دهید.
ســاخــتـــار