برنامه نویسی 103 بازدید

هنگامی که یک پروژه جدید را آغاز می‌کنیم، مطمئناً بی‌درنگ شروع به کدنویسی نمی‌کنیم. ابتدا باید هدف و حوزه پروژه را تعریف کنیم و سپس ویژگی‌ها و خصوصیات آن را تعیین کنیم. پس از این که شروع به کدنویسی کردید نیز در صورتی که روی یک پروژه پیچیده‌تر کار می‌کنید، باید الگوهای طراحی انتخاب کنید که مناسب پروژه شما باشد.

الگوی طراحی چیست؟

منظور از الگوی طراحی در مهندسی نرم‌افزار راه‌حلی با قابلیت استفاده مجدد برای مسائل با رویداد مکرر در هنگام طراحی نرم‌افزار است. الگوهای طراحی نماینده بهترین رویه‌های مورد استفاده از سوی توسعه‌دهنده‌های نرم‌افزار باتجربه است. یک الگوی طراحی را می‌توان نوعی قالب برنامه‌نویسی در نظر گرفت.

چرا باید از الگوهای طراحی استفاده کنیم؟

بسیاری از برنامه‌نویس‌ها یا فکر می‌کنند که الگوی طراحی، هدر دادن زمان است و یا این که نمی‌دانند چگونه باید از آن‌ها به درستی استفاده کنند. اما استفاده از الگوهای طراحی مناسب می‌تواند به نوشتن کدهای بهتر و با درک‌پذیری بالاتر کمک کند و چنین کدی می‌تواند به روشی آسان‌تر نگهداری شود، زیرا درک آن ساده‌تر است.

مهم‌تر از همه این که الگوهای طراحی به توسعه‌دهنده‌های نرم‌افزار، فرهنگ واژگان مشترکی می‌دهد که بدین ترتیب می‌توانند با هم تعامل برقرار کنند. این الگوها مقصود کد را بی‌درنگ به هر فردی که کدنویسی بداند نشان می‌دهند.

برای نمونه اگر از الگوی دکوراتور (decorator) در پروژه خود استفاده می‌کنید، در این صورت یک برنامه‌نویس جدید می‌تواند بی‌درنگ بفهمد که هر قطعه از کد چه کاری انجام می‌دهد و می‌تواند به جای تلاش برای درک کاری که کد انجام می‌دهد، روی حل مسئله تجاری متمرکز شود.

اینک که دانستید الگوهای طراحی چه هستند و چرا مهم هستند، به معرفی الگوهای طراحی پراستفاده در زبان جاوا اسکریپت می‌پردازیم.

الگوی ماژول (Module Pattern)

یک ماژول تکه‌ای از کد خودکفا است و بدین ترتیب می‌توان ماژول را بدون هیچ اثر جانبی روی بخش‌های دیگر کد به‌روزرسانی کرد. همچنین ماژول‌ها با ایجاد دامنه مجزا برای متغیرها، امکان جلوگیری از آلودگی فضای نام را ایجاد می‌کنند. ضمناً می‌توان با جدا کردن ماژول‌ها از بخش‌های دیگر کد، از آن‌ها به صورت مجدد در پروژه‌های دیگر استفاده کرد.

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

پلتفرم‌هایی مانند bit می‌توانند به تبدیل ماژول‌ها و کامپوننت‌ها به قطعه‌های سازنده مشترک کمک کنند. بدین ترتیب ماژول‌ها را می‌توان به اشتراک گذاشت، کشف کرد و یا از هر پروژه‌ای توسعه داد. ماژول‌ها بدون نیاز به هیچ‌گونه بازسازی (refactoring) روشی سریع و مقیاس‌پذیر برای اشتراک و استفاده مجدد از کد محسوب می‌شوند.

جاوا اسکریپت برخلاف زبان‌های دیگر برنامه‌نویسی به modifier ها دسترسی ندارد و از این رو نمی‌توان یک متغیر را به صورت عمومی یا خصوصی تعریف کرد. بدین ترتیب الگوی طراحی برای ارزیابی مفهوم کپسوله‌سازی (encapsulation) نیز استفاده می‌شود.

این الگو از IIFE یعنی «عبارت تابعی با فراخوانی بی‌درنگ» (immediately-invoked function expression)، کلوژر (Closure) و دامنه تابع برای شبیه‌سازی این مفهوم استفاده می‌کند. برای مثال:

کد فوق از آنجا که یک IIFE است، بی‌درنگ اجرا می‌شود و شیء بازگشت یافته به متغیر myModule منسوب می‌شود. به دلیل وجود کلوژر، شیء بازگشتی می‌تواند حتی پس از این که IIFE خاتمه یافت، همچنان به تابع‌ها و مغیرهای تعریف شده درون آن دسترسی داشته باشد.

بنابراین متغیرها و تابع‌های تعریف شده درون IIFE بنا به ضرورت از دامنه بیرونی پنهان شده‌اند و از این رو آن را برای متغیر myModule به صورت خصوصی تعریف کرده‌اند.

پس از این که کد اجرا شد، متغیر myModule به صورت زیر خواهد بود:

بنابراین می‌توانیم متد publicMethod را فراخوانی کنیم که به نوبه خود متد privateMethod را فراخوانی می‌کند. برای نمونه:

الگوی Revealing Module

الگوی Revealing Module نسخه اندکی بهبود یافته از الگوی ماژول است که از سوی کریستین هیلمان (Christian Heilmann) ارائه شده است. مشکل الگوی ماژول این است که در آن باید تابع‌های عمومی جدیدی را صرفاً برای فراخوانی تابع‌ها و متغیرهای خصوصی ایجاد کنیم.

در این الگو مشخصات شیء بازگشتی را به تابع‌های خصوصی که می‌خواهیم به صورت عمومی افشا کنیم، نگاشت می‌نماییم. به همین دلیل آن را الگوی ماژول افشایی (Revealing Module) می‌نامیم. برای مثال:

این الگو امکان درک این که کدام تابع و متغیرها می‌توانند دسترسی عمومی داشته باشند تسهیل می‌کند و به افزایش خوانایی کد کمک می‌کند.

پس از این که کد اجرا شد، myRevealingModule به صورت زیر خواهد بود:

می‌توان (myRevealingModule.setName(‘Mark’ را که ارجاعی به متد درونی publicSetName و ()myRevealingModule.getName را که ارجاعی به متد درونی publicGetName است، فراخوانی کرد. برای مثال:

مزیت‌های الگوی Revealing Module نسبت به الگوی Module را می‌توان به صورت زیر جمع‌بندی کرد:

  • در این الگو می‌توان اعضا را با تغییر دادن یک خط کد در عبارت بازگشتی از حالت عمومی به خصوصی و برعکس تبدیل کرد.
  • شیء بازگشتی شامل هیچ تعریف تابعی نیست و همه بخش راست عبارت درون IIFE تعریف شده است. بدین ترتیب خوانایی کد افزایش می‌یابد.

ماژول‌های ES6

جاوا اسکریپت تا پیش از ES6 ماژول‌های درونی نداشت و از این رو توسعه‌دهندگان باید روی کتابخانه‌های شخص ثالث یا الگوی module برای پیاده‌سازی ماژول‌ها تکیه می‌کردند. ماژول‌های ES6 در فایل‌ها ذخیره می‌شوند و در هر فایل تنها یک ماژول می‌توان داشت. هر چیزی درون یک ماژول به طور پیش‌فرض خصوصی است. تابع‌ها، متغیرها و کلاس‌ها با استفاده از کلیدواژه export افشا می‌شوند. کد درون یک ماژول همواره در حالت strict mode اجرا می‌شود.

اکسپورت کردن یک ماژول

دو روش برای اکسپورت کردن اعلان یک تابع و متغیر وجود دارد. روش اول با افزودن کلیدواژه export در ابتدای اعلان تابع و متغیر است. برای نمونه:

روش دوم از طریق افزودن کلیدواژه export در انتهای کدِ شامل نام‌های تابع‌ها و متغیرهایی که می‌خواهیم اکسپورت کنیم است. برای مثال:

ایمپورت کردن یک ماژول

همانند اکسپورت کردن ماژول، دو روش برای ایمپورت کردن یک ماژول با استفاده از کلیدواژه import وجود دارد. برای نمونه:

ایمپورت چند آیتم به یک باره

ایمپورت کردن همه ماژول

ایمپورت و اکسپورت را می‌توان با نام مستعار انجام داد

اگر می‌خواهید از تصادم نام (name collision) اجتناب کنید، می‌توانید نام اکسپورت را هم در زمان اکسپورت و هم ایمپورت تغییر دهید. برای نمونه:

تغییر نام یک اکسپورت

تغییر نام یک ایمپورت

الگوی سینگلتون (Singleton)

سینگلتون شیئی است که تنها یک بار می‌توان از آن وهله سازی کرد. الگوی سینگلتون یک وهله جدید از یک کلاس را تنها در صورتی می‌سازد که قبلاً وهله دیگری ایجاد نشده باشد. اگر وهله‌ای از قبل موجود باشد، سینگلتون صرفاً یک ارجاع به آن شیء بازمی‌گرداند. فراخوانی‌های مکرر به سازنده، صرفاً ارجاع‌هایی به همان شیء یکسان بازمی‌گردانند.

زبان جاوا اسکریپت همواره سینگلتون های داخلی خود را داشته است؛ اما ما همیشه آن‌ها را سینگلتون نمی‌نامیدیم و گاهی اوقات آن‌ها را صرفاً شیء می‌نامیم. برای نمونه:

از آنجا که هر شیء در جاوا اسکریپت مکان یکتایی از حافظه را اشغال می‌کند، هنگامی که شیء user را فراخوانی می‌کنیم، اساساً ارجاعی به آن شیء را به دست می‌آوریم.

اگر تلاش کنیم که متغیر user را به متغیر دیگری کپی کنیم و آن متغیر را تغییر دهیم، باید به صورت زیر عمل کنیم:

در این حالت می‌بینیم که هر دو شیء تغییر یافته‌اند، چون اشیا در جاوا اسکریپت با ارجاع ارسال می‌شوند و نه با مقدار. از این رو تنها یک شیء منفرد در حافظه وجود دارد. برای نمونه:

الگوی سینگلتون را می‌توان با استفاده از تابع سازنده نیز پیاده‌سازی کرد. روش کار به صورت زیر است:

هنگامی که تابع سازنده فراخوانی می‌شود، بررسی می‌کند که آیا شیء instance وجود دارد یا نه. اگر شیء وجود نداشته باشد، متغیر this را به متغیر instance انتساب می‌دهد. و اگر شیء وجود داشته باشد، صرفاً آن شیء را بازمی‌گرداند.

سینگلتون ها را می‌توان با استفاده از الگوی ماژول نیز پیاده‌سازی کرد. روش کار به صورت زیر است:

در قطعه کد فوق، یک وهله جدید به وسیله فراخوانی متد singleton.getInstance ایجاد می‌شود. اگر یک وهله از قبل وجود داشته باشد، این متد صرفاً آن وهله را بازمی‌گرداند، و اگر وهله‌ای وجود نداشته باشد، یک وهله حدید را از طریق فراخوانی تابع ()init ایجاد می‌کند.

الگوی factory

الگوی factory الگویی است که از متدهای factory برای ایجاد شیءها بدون تعیین کلاس دقیق یا تابع سازنده‌ای که شیء از آن ایجاد شده است، استفاده می‌کند.

الگوی factory برای ایجاد شیءها بدون افشا کردن منطق وهله سازی مورد استفاده قرار می‌گیرد. این الگو می‌تواند هنگام نیاز به ایجاد شیء متفاوت بسته به شرایط خاص مورد استفاده قرار گیرد. برای نمونه:

در این کد یک کلاس car و یک کلاس truck با برخی مقادیر پیش‌فرض ایجاد کرده‌ایم که برای ایجاد اشیای جدید car و truck استفاده می‌شوند. همچنین یک کلاس VehicleFactory تعریف کرده‌ایم که شیء جدیدی را بر مبنای مشخصه vehicleType دریافتی در شیء options ایجاد کرده و بازمی‌گرداند.

می‌بینید که یک شیء جدید factory از کلاس VehicleFactory ایجاد کرده‌ایم. پس از آن می‌توانیم یک شیء car یا truck جدید را با فراخوانی factory.createVehicle و ارسال شیء options با مشخصه vehicleType و با مقدار car یا truck ایجاد کنیم.

الگوی دکوراتور (Decorator)

الگوی دکوراتور برای بسط دادن کارکردهای یک شیء بدون تغییر دادن کلاس موجود یا تابع سازنده استفاده می‌شود. این الگو می‌تواند برای افزودن ویژگی‌های یک شیء بدون اصلاح کد زیربنایی تشکیل‌دهنده‌اش استفاده شود. نمونه ساده‌ای از این الگو به صورت زیر است:

نمونه عملی‌تری از این الگو به صورت زیر است. فرض کنید هزینه یک خودرو بسته به تعداد ویژگی‌هایی که دارد متفاوت است. بدون استفاده از الگوی دکوراتور باید کلاس‌های مختلفی برای ترکیب‌های متفاوت از ویژگی‌ها ایجاد کنیم که هر یک متد هزینه برای محاسبه قیمت خودرو دارد. برای نمونه:

اما با بهره‌گیری از الگوی دکوراتور می‌توان یک کلاس پایه car ایجاد کرد و هزینه پیکربندی‌های مختلف را با استفاده از تابع‌های دکوراتور به شیء آن افزود. برای نمونه:

ابتدا یک کلاس پایه car برای ایجاد شیءهای car ایجاد می‌کنیم. سپس دکوراتورهایی برای ویژگی‌هایی که می‌خواهیم به آن اضافه کنیم ایجاد کرده و شیء car را به صورت یک پارامتر ارسال می‌کنیم. سپس تابع هزینه این شیء را که هزینه به‌روزرسانی شده car را بازگشت می‌دهد override می‌کنیم و مشخصه جدیدی به آن شیء اضافه می‌کنیم که نشان می‌دهد این ویژگی افزوده شده است.

برای افزودن ویژگی جدید باید به صورت زیر عمل کنیم:

در نهایت می‌توانیم بهای خودرو را به صورت زیر محاسبه کنیم:

سخن پایانی

در این نوشته در مورد الگوهای مختلف طراحی مورد استفاده در جاوا اسکریپت نکاتی آموختیم؛ اما باید بدانید الگوهای دیگری نیز وجود دارند که در این نوشته بررسی نکردیم؛ اما در جاوا اسکریپت می‌توانند پیاده‌سازی شوند.

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

اگر این مطلب برایتان مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *