برنامه نویس اندروید - https://www.linkedin.com/in/iryebohs/
الگویِ طراحی Command (جاوا و کاتلین)
فرض کنید رفتید رستوران ، به گارسون سفارشتون رو میدید ، گارسون سفارش رو میبره تحویل آشپزخونه و بر حسب سفارشتون یکی آمادهاش میکنه ، اگه کباب بخواید ، کباب زن براتون کباب میذاره رو منقل و اگه پیتزا بخواید یک نفر دیگه اون مسئول پخت پیتزا با فِر میشه ، الگویِ طراحی Command دقیقا همینه !
این الگو جزو طبقهبندی Behavioral ها حساب میشه چون به رفتارهای الگوریتم و ارتباط اجزا با هم کار داره ، ما در این الگو چند بخش داریم :
Command
یک interface که شامل تعریفِ توابع اصلی هستند ، مثلا تابع execute ، یا تابع undo برای اینکه Command ای که اجرا کردید رو به حالت قبل برگردونید (یا هر تابعی که شما به نظرتون نیازه مثل redo و ... ، یا فرضا دارید برای کپی پیست یک Command درست میکنید و اونا رو هم میتونید لحاظ کنید ، من در کدی که در این مقاله میارم فقط execute و undo رو مثال میزنم)
ConcreteCommand
معنی Concrete میشه "بتن" ، پس این کلاس بدنه یک Command هست ، یعنی ما بر اساس Command این کلاس رو میسازیم و توابعی که در Command داشتیم رو بر حسب این کلاس پیاده سازی میکنیم ، چرا میگم "بر حسب این کلاس" ؟ چون میتونیم انواع مختلف از این کلاس رو داشته باشیم (در مثال متوجه میشید)
Invoker
کلاسی که Command رو به درخواست مورد نظر میرسونه ، مثلا یک ریموت کنترل میشه یک Invoker
Receiver
درخواست کننده اون Command ، یعنی کسی که در انتها Command رو دریافت میکنه و متناظر اون یک تغییری در خودش میده
صورت مساله
برنامهای مینویسیم که بتواند رنگِ کلاسی به اسم Light را بر حسب Command به سه نور قرمز ، آبی و سفید تغییر دهد ، برای این کار اول از همه همهی توابع مورد نیاز برای یک Command رو در یک Interface تعریف میکنیم :
حالا نیاز داریم که کلاس Receiver رو که همون Light میشه بسازیم ، این کلاس یک color در خودش داره و تعدادی تابع برای تغییر رنگِ color :
حالا باید ConcreteCommand ها رو بسازیم ، من در این مثال سه ConcreteCommand میسازم برای هر رنگ و این سه کلاس رو از کلاسی به اسم LightCommandMother مشتق میکنم ، LightCommandMother یک کلاس abstact هست که بدنه تابع undo در اون پیاده شده و یک Receiver هم به عنوان ورودی میگیره ، این کلاس یک اِلِمان به عنوان lastStatus داره که رنگِ حالت قبلی رو در خودش داره (البته برای مثالهای پیچیده نباید این طوری بنویسید و به جاش میتونید از شئ یک clone بسازید و در تابع undo کلِ اون شئ رو درون شئ جدید بریزید) ، باقی ConcreteCommand ها از این کلاس مشتق میشن و تابع execute درون اونها پیاده میشه :
حالا نیاز به یک Invoker داریم (invoke در لغت به معنی فراخوانی هست) که اسمشو میذاریم RemoteControl ، در این کلاس یک Stack (پشته) از Commandها داریم و یک تابع pressButton ، در ورودیِ pressButton یک Command قرار میگیره که اون رو execute کرده و درون stack قرار میده ، در این کلاس تابع undoButton عمل undo رو انجام میده ، اگر stack خالی بود که هیچی وگرنه آخرین Command رو pop میکنه و تابع undo اونو صدا میزنه :
و درآخرم نیاز به کدِ Client هست که بیاد از چیزایی که تا الان تعریف کردیم استفاده کنه ، مثلا چندبار دکمه فشار بده و یکبار هم undo کنه :
و تمام !
حالا چه زمانهایی باید از این الگو استفاده کنیم ؟
- زمانی که به سابقه و history از درخواست ها نیاز داریم (مثلا با stack)
- زمانی که نیاز داریم درخواست کنندهی Command اطلاعی در مورد پیادهسازی نداشته باشه (یعنی کدها جدا باشن و پیادهسازیها مخفی شده باشند)
- لایهبندی ایجاد شده در این الگو موجب میشه بعدا اگه لازم شد بهتر و راحتتر و دستِ باز تر تغییرات مورد نیازمون رو در کد انجام بدیم
- و ...
باقی مقالات در مورد الگویهای طراحی رو در این مقاله بخونید .
من رو در لینکدین و اینستاگرام دنبال کنید ???
اگه دوست داشتید میتونید به صفحه Spotify بنده هم برید و موسیقی های منو گوش بدید ???
مطلبی دیگر از این انتشارات
راهنمای نوشتن کدهای تمیزتر در برنامه نویسی
مطلبی دیگر از این انتشارات
کد در خدمت جامعه
مطلبی دیگر از این انتشارات
برنامه نویسی را از کجا و چطور شروع کنیم ؟