اهداف الگوهای طراحی

مقدمه: اینجا فقط به هدف هر الگو و اینکه این الگو چه مسئله ای را حل میکند می پردازم. و ببینید در حال حاضر مشکلی که داریم با کدام الگو می توان حل کرد (خوراندن یک الگو به مشکل ممنوع)الگو های ساختاری Structuralاین الگوها به روابط و تعامل بین اشیا و ترکیب شدن آنها با یکدیگر برای شکل دادن سازه ها و اشیا پیچیده تر تمرکز دارند.این نوع الگوها می توانند هنگام طراحی یا پس از آن در حین نگهداری و توسعه استفاده شوند.DecoratorProxyBridgeCompositeFlyweightAdapterFacadeهدف الگوی Decorator :افزودن وضعیت یا رفتار جدید به طور پویا به اشیا.این بار مثال را با شیرینی و کیک پیش می‌بریم.فرض کنید شما قصد پخت کیک و نان را دارید. طبیعی است که برای اینکار یک واسط را تعریف کرده و عمل «پختن» را در آن اعلام می‌کنید تا هر کلاسی که قصد پیاده سازی این واسط را داشت، «پختن» را انجام دهد. در ادامه یک کلاس بنام کیک ایجاد خواهید کرد و شروع به پخت آن می‌کنید.خوب احتمالا الان کیک آماده‌است و می‌توانید آن‌را میل کنید! ولی یک سؤال. تکلیف شخصی که کیک با روکش کاکائو دوست دارد و شمایی که کیک با روکش میوه‌ای دوست دارید چیست؟ این را چطور در پخت اعمال کنیم؟ یا منی که نان کنجدی می‌خواهم و شمایی که نان برشته‌ی غیر کنجدی می‌خواهید چطور؟احتمالا می‌خواهید سراغ ارث بری رفته و سناریوهای این چنینی را پیاده سازی کنید. ولی در مورد ارث بری، اگر کلاس sealed (NotInheritable) باشه چطور؟احتمالا همین دو تا سؤال کافی‌است تا در پاسخ بگوئیم، گره‌ی کار، با الگوی Decorator باز می‌شود و همین دو تا سؤال کافی‌است تا اعلام کنیم که این الگو، از جمله الگوهای بسیار مهم و پرکاربرد است. ادامهبه عنوان مثال تصویر زیر را در نظر بگیرید. روش های متعددی برای اضافه کردن یک موجودیت یا صفت جدید به یک تصویر وجود دارد، به عنوان نمونه، اضافه کردن حاشیه به اطراف آن، و یا اضافه کردن تگ مرتبط با متن تصویر به آن. چنین مواردی که به تصویر اضافه می شوند، می توانند در بالا با پایین آن نمایش داده شوند. ادامهبیشترهدف الگوی Proxy :استفاده از یک شی واسطه به منظور جلوگیری از دسترسی مستقیم به شی اصلی و متمرکز سازی کنترل دسترسی.همه کاربران کامپیوتر در ایران به خوبی با کلمه پروکسی آشنا هستند. پروکسی به معنی نماینده یا واسط است و پروکسی واسطی است بین ما و شیء اصلی. پروکسی در شبکه به این معنی است که سیستم شما به یک سیستم واسط متصل شده است که از طریق پروکسی محدودیت‌های دسترسی برای آن تعریف شود. در اینجا هم پروکسی در واقع به همین منظور استفاده می‌شود. ادامههدف الگوی Bridgeجدا کردن انتزاع و پیاده سازی از یکدیگر به منظور اینکه بتوان هرکدام را بطور مستقل از دیگری توسعه داد.سناریو زیر را در نظر بگیرید:قصد دارید تا در برنامه‌ی خود ارسال پیام از طریق پیامک و ایمیل را راه اندازی کنید. هر کدام از این روش‌ها نیز برای خود راه‌های متفاوتی دارند. برای مثال ارسال پیامک از طریق وب سرویس یا یک API خارجی و غیره.کاری را که می‌توان انجام داد، بشرح زیر نیز می‌توان بیان نمود:ابتدا یک Interface ایجاد می‌کنیم (IBridge) و در آن متد Send را قرار می‌دهیم. این متد یک پارامتر ورودی از نوع رشته می‌گیرد و به کمک آن میتوان اقدام به ارسال پیامک یا ایمیل یا هر چیز دیگری نمود. کلاس‌هایی این واسط را پیاده سازی می‌کنند که یکی از روش‌های اجرای کار باشند (برای مثال کلاس WebService که یک روش ارسال پیامک یا ایمیل است). ادامهیکی از مهمترین کاربرد های الگوی طراحی Bridge زمانی است که نسخه جدیدی از یک نرم افزار متولد می شود که قرار است جایگزین نسخه قدیمی آن شود و قرار هست که نسخه قدیمی این نرم افزار نیز به همان قدرت قبلی به کار خود ادامه دهد. تا مشتریان قبلی بتوانند همچنان از نرم افزار خریداری شده خود استفاده کنند. کد برنامه نیازی ندارد تا تغییر کند، زیرا ساختار کد به دلیل تطابق با انتزاع (Abstraction) موجود مشخص است، ولی استفاده کننده خود باید مشخص کند که از کدام نسخه می خواهد در برنامه استفاده کند. ادامهبیشترهدف الگوی Compositeتعریف ساختار اشیایی که interface مشابهی داشته باشند و بتوانند درختواره ای سلسله مراتبی ایجاد کرد.برای مثال، ساختار کارمندان یک سازمان را در نظر بگیرید. در این ساختار رئیس یا CEO در راس این درخت قرار دارد و در ادامه دسته ای از مدیران، کارفرمایان و سپس کارمندان جزء.در صورتی که CEO، مدیران، کارفرمایان اشیاء مرکب ای باشند که زیردستان خود را مدیریت می کنند، آنگاه کارمندان یا کارمندان جزء اشیاء منفردی هستند که در این ساختار درختی به صورت برگ ظاهر می شوند.به عنوان یک مثال دیگر، ساختار file های کامپیوتر در نظر بگیرید. این ساختار سلسله مراتبی از پوشه ی ریشه شروع می شود تا به آخرین فایل های ممکن برسد. ادامهبیشترهدف الگوی Flyweightفاکتورگیری از اشیا تکراری و صرفه جویی در مصرف حافظه.سناریوی زیر را در نظر بگیرید:فرض کنید از شما خواسته شده است تا یک پردازشگر متن را بنویسید. خوب در این پردازشگر با یک‌سری کاراکتر روبرو هستید که هر کاراکتر احتمالا آبجکتی از نوع کلاس خود می‌باشد؛ برای مثال آبجکت XYZ که آبجکتی از نوع کلاس A هست و برای نمایش کاراکتر A استفاده می‌شود. این آبجکت‌ها دارای دو دسته خصیصه هستند: (مطالعه بیشتر )خصیصه‌های ثابت: یعنی همه کاراکترهای A دارای یک شکل مشخص هستند. در واقع مشخصات ذاتی آبجکت می‌باشند.خصیصه‌های پویا: یعنی هر کاراکتر دارای فونت، سایز و رنگ خاص خود است. در واقع خصیصه‌هایی که از یک آبجکت به آبجکت دیگر متفاوت هستند .خوب احتمالا در ساده‌ترین راه حل، به ازای تک تک کاراکترهایی که کاربر وارد می‌کند، یک آبجکت از نوع کلاس متناسب با آن ساخته می‌شود. ولی بحث مهم این است که با این همه آبجکت که هر یک مصرف خود را از حافظه دارند، می‌خواهید چکار کنید؟ احتمالا به مشکل حافظه برخورد خواهید کرد! پس باید یک سناریوی بهتر ایجاد کرد.سناریوی پیشنهادی این است که برای هر نوع کاراکتر، یک کلاس داشته باشیم، همانند قبل(یک کلاس برای A یک کلاس برای B و غیره) و یک استخر پر از آبجکت داشته باشیم که آبجکت‌های ایجاد شده در آن ذخیره شوند.سپس کاربر، کاراکتر A را درخواست می‌کند. ابتدا به این استخر نگاه می‌کنیم. اگر کاراکتر A موجود بود، آن را برمی‌گردانیم و اگر موجود نبود، یک آبجکت از نوع A می‌سازیم، سپس این آبجکت را در استخر ذخیره می‌کنیم و آبجکت را بر می‌گردانیم. در این صورت اگر کاربر دوباره درخواست A را کرد، دیگر نیازی به ساخت آبجکت جدید نیست و از آبجکت قبلی می‌توانیم استفاده نماییم. با این شرایط تکلیف خصایص ایستا مشخص است. ولی مشکل مهم با خصایص پویا این است که می‌توانند بین آبجکت‌ها متفاوت باشند که برای این هم یک متد در کلاس‌ها قرار می‌دهیم تا این خصایص را تنظیم نماید. ادامهبیشترهدف الگوی Adapterفراهم کردن امکان استفاده از کلاسی با interface ناهمگون در یک برنامه ی دیگر.از الگوی Adapter برای ادغام شدن با یکسری اجزاء خارجی استفاده می شود که این اجزاء از نظر عملکرد یکسان هستند و فقط نحوه فراخوانی توابعشان کمی با هم فرق دارند. فرض کنید یک کلاس Employee با یک متد PrintEmployee داریم و قرار است با یک کلاس ارائه دهنده کارمند قراردادی با نام EmployeeDetail و یک تابع با نام ListEmployee تعامل داشته باشد.در این مثال می توانیم یک کلاس adapter (تطبیقی) بسازیم که کلاس خارجی EmployeeDetail را بپوشاند. بنابراین فراخوانی متد PrintEmployee() در adapter به متد ListEmployee() کلاس خارجی واگذار (Delegate) می شود. ادامهاز الگوهای ساختاری برای ترکیب کلاسها و اشیاء (Objects)،در جهت ایجاد ساختارهای بزرگتر استفاده می‌شود.به بیان ساده‌تر الگوهای ساختاری با ترکیب کلاسها و آبجکتها،قابلیت‌های کلاسهای غیر مرتبط را در قالب یک Interface(منظور ظاهر) در اختیار Client (منظور کلاس یا متد استفاده کننده می‌باشد) قرار می‌دهند.الگوهای ساختاری با استفاده از ارث بری به ترکیب Interfaceها پرداخته و آنها را پیاده سازی می‌نمایند.استفاده از الگوهای ساختاری برای توسعه کتابخانه هایی (Library) که مستقل از یکدیگر می‌باشند،اما در کنار هم مورد استفاده قرار می‌گیرند،بسیار مفید است. ادامهبیشترهدف الگوی Facadeخلاصه سازی، ساده سازی و متمرکزسازی interface یک سیستم شلوغ و پیچیده متشکل از تعداد زیادی کلاس و زیر سیستم به یک interface سبک ، ساده و سطح بالا.این الگو یک کلاس یا یک سیستمی را با متدها و رویدادهایی ساده، در اختیار ما قرار می‌دهد و در یک لحظه، تنها با یک کلاس واحد سر و کله می‌زنیم. احتمالا بسیاری از شما از این الگو استفاده کرده‌اید، ولی شاید با اسم آن آشنا نبوده‌اید.کار این کلاس در واقع ترکیب کلاس‌ها و کتابخانه‌های کاری مشخص است که نیاز به ارتباط با یکدیگر را دارند. به عنوان مثال یک برنامه کتابخانه، برای وظیفه‌ای چون امانت یک کتاب نیاز است تا چندین کلاس مختلف را با یکدیگر به کار بگیرد که این وظایف شامل موارد زیر می‌باشند:1- بررسی وجود کتاب2- بررسی تعداد موجود یک کتاب در کتابخانه3- بررسی وضعیت امانی کتاب (آیا کتاب در دست کسی از قبل امانت است؟ یا کتاب برای امانت آزاد است؟)4- در صورتی که کتابی بیش از زمان مورد نظر در دست کسی امانت است، با یک پیامک از او بخواهیم که کتاب را بازگرداند.تمامی موارد بالا تنها قسمتی از انجام یک عمل ساده هستند که در یک گروه جای می‌گیرند؛ ولی در واقع از چندین کلاس جدا مثل کلاس کتاب، امانت، سیستم پیامکی و ... استفاده شده است . الگوی Facade به ما کمک می‌کند تا پیچیدگی و تعداد خطوط اجرا را در سطوح بالاتر مخفی سازیم و تنها با صدا زدن یک یا چند متد ساده، کار را به اتمام برسانیم. این کار باعث کاهش کد و خوانایی برنامه در سطوح بالاتر می‌شود.بیشترالگو های ایجادی Creational این الگوهای به ساختار اشیا و ارجاع به آنها پرداخته و با انتزاعی کردن روند نمونه سازی از کلاس ها، مسئولیت این کار را خودشان بر عهده میگیرند. یعنی دیگر نیازی نیست کلاینت، خودش به طور صریح از یک کلاس نمونه سازی کند. این الگوها اتصال بین کلاس ها را ضعیف کرده و loose coupling (اتصال سست) را ترویج میدهند و با متمرکزسازی مسئولیت ایجاد اشیا پیچیده در یک نقطه ی متمرکز، پایبندی به اصول SRP و SoC را فراهم میکنند. https://virgool.io/@espiar/%D8%A7%D8%B5%D9%88%D9%84-solid-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%B3%D8%A7%D8%AF%D9%87-%D9%88-%D8%AE%D9%84%D8%A7%D8%B5%D9%87-jglgxrpgdqhf https://virgool.io/@espiar/%D8%A7%D8%B5%D9%88%D9%84-solid-%D8%AF%D8%B1-clean-code-%D9%82%D8%B3%D9%85%D8%AA6-iarbkbnyerp8 هدف این الگو ها این است که یک سیستم را از چگونگی ساخت، تشکیل و ارائه ی اشیایشان جدا کنند. این الگو ها انعطاف پذیری سیستم را از نظر این که چه کسی،چگونه و چه هنگام، فلان شی را ایجاد میکند افزایش میدهد. الگو های ایجادی Creational دانش این که چه کلاس هایی توسط سیستم استفاده میشود را کپسوله کرده و جزییات نمونه سازی از آنها را پنهان میکنند.مطلب مهمی که باید درک کنید این است که یک سیستم بر اساس وراثت و نمونه سازی مستقیم از کلاس ها باعث سفت و سخت شدن سیستم و افزایش tight coupling (ارتباط محکم و نزدیک-اتصال سفت) میشود. هدف این الگوها این است که این اتصال قوی و نزدیک (close coupling) را بشکنند.PrototypeFactory MethodSingletonAbstract FactoryBuilderهدف الگوی Prototypeسرعت بخشیدن به روند نمونه سازی و ایجاد اشیا با کپی سازی از نمونه های از پیش موجود.فرض کنید در حال پختن یک کیک هستید. ابتدا کیک را می‌پذید و سپس آن را تزیین می‌کنید. عملیات پختن کیک، فرآیند ثابتی است و تزیین کردن آن متفاوت. گاهی کیک را با کاکائو تزیین می‌کنید و گاهی با میوه و غیره. ادامهالگوی طراحی ای است که اشیاء را مجبور می کند تا در زمان ساخت، کپی یا شبیه سازی شوند.آیا کپی شی هم مهم است؟جواب ساده است. زمانی که اشیاء زیادی برای کار کردن نیاز باشد و ساخت آنها بسیار هزینه بر باشد، کپی کردن آنها می تواند به بهبود کارایی کمک کند.ادامهنمونه‌های اولیه برای انجام آزمایش‌های مختلف قبل از شروع تولید انبوه محصولات استفاده می‌شوند. اما در این الگوی طراحی، نمونه‌های اولیه به منظور انجام آزمایشات مختلف یا کنترل کیفیت استفاده نمی‌شوند. نمونه‌های ساخته شده در این تکنیک به صورت مستقیم در بخش‌های مورد نیاز در نرم افزار استفاده می‌شوند. بنابراین، تقریبا بهترین مثال از این الگوی طراحی در دنیای واقعی فرآیند تقسیم سلولی است.تصور کنید که یک کلاس به اسم سلول (Cell) در نرم افزار تعریف شود. برای اینکه این سلول به یک موجود تکامل یافته تبدیل شود، نیاز به تکثیر و نمونه سازی دارد. بنابراین به هزاران یا میلیون‌ها شی از این کلاس نیاز خواهیم داشت تا اندام‌های مختلف یک موجود زنده را تشکیل دهند و هر کدام به وظیفه خاص خود بپردازد. حال تصور کنید، اگر می‌خواستید همه این اشیا را به صورت مستقیم و یک به یک بسازید و پارامترهای آن‌ها را مقدار دهی کنید، چه میزان از زمان شما مصرف می‌شد.بر این اساس بهترین راه برای انجام این کار، به کارگیری الگوی طراحی پروتوتایپ خواهد بود. زیرا در این الگو سلول‌ها بر اساس سلول اولیه کپی خواهند شد و دیگر نیازی به ساخته شدن سلول‌ها و مقدار دهی پارامترهای آن‌ها بر اساس سلول اولیه به صورت یک به یک نخواهد بود. با توجه به این نکته که در فرآیند تقسیم سلولی، سلول‌های جدید از سلول اولیه ایجاد می‌شوند می‌توان اینگونه گفت که سلول اصلی به عنوان یک نمونه اولیه یا Prototype عمل می‌کند. ادامهبیشترهدف الگوی Factory Methodمتمرکزسازی نمونه سازی از کلاس های مشابه و کاهش اتصال مستقیم به محصول.اگر یک میوه فروشی موجود باشد که در کل روزهای سال میوه آوکادو می فروشد. این میوه فروشی باید مطمئن باشد که می تواند در طول سال می تواند این میوه را از کشاورزان تهیه نماید. این میوه فروشی باید از نواحی و کشورهای مختلف این میوه را در طول سال خریده و در داخل فروشگاه عرضه نماید. این میوه در کشورهای اسپانیا، آفریقای جنوبی و کنیان در فصل های متفاوتی رشد می کند. الگوی Factory Method شبیه به این میوه فروشی عمل می کند.اگر هرکدام از کشورهای تولید کننده آوکادو را به عنوان یک کلاس در نظر بگیریم و هرکدام اینترفیس IProduct را پیاده سازی می کند. بنابراین این کشورها می توانند آوکادو برای میوه فروشی فراهم کنند. ادامهبیشترهدف الگوی Singletonتعریف کلاسی که در سرتاسر برنامه تنها یک نمونه از آن بتوان ایجاد کرد.خیلی وقت ها نیاز است که فقط یک نمونه از یک کلاس ساخته شود. مثلاً وقتی که نمی خواهیم وضعیت شی تغییر کند و یا می خواهیم class را به صورت stateless نگه داریم.و به دلایل مختلفی نباید از کلاس های static استفاده کنیم. برخی از این دلایل عبارتند از:1- موارد مختلفی هست هست که می خواهید Interface ها را در یک کلاس پیاده سازی کنید (برای مثال پیاده سازی IOC) و به جای پیاده سازی کلاس به صورت static، آن را به صورت Singleton پیاده سازی می کنیم.2- در صورت نیاز، می توانید از یک کلاس singleton به صورت پارامتر یک متد استفاده کنید در حالی که نمی توان این کار را با کلاس static انجام داد.ادامهبیشترهدف الگوی Abstract Factoryتعریف ساختار یک کلاس Factory و تعدادی محصول به شکل انتزاعی به گونه ای که Factoryهای مختلف مطابق آن بتوانند خانواده ای از محصول های متفاوت را تولید کرده و در اختیار client قرار بدهند.به منظور ایجاد یک کارخانه برای تولید انواع قالب‌های مختلف برای عناصر مختلف یک صفحه وب استفاده می‌شود. زیرا یک وبسایت قادر است از موتور‌های رندر مختلف به صورت همزمان پشتیبانی کند. به دلیل تفاوت در کدهای مربوط به هر یک از موتور‌های رندر قالب، ایجاد Template‌ها باید توسط کارخانه اختصاصی خود انجام شوند.ادامهبیشترهدف الگوی Builderجدا کردن دستورالعمل تولید یک محصول از کسی که محصول را تولید میکند و نظارت بر نحوه ی تولید، توسط یک مدیر به منظور این که بتوان همان محصول را به شکلی متفاوت با قابلیتی متفاوت تولید کرد.سناریوی زیر را در نظر بگیرید:از شما خواسته شده است تا نحوه‌ی ساخت تلفن همراه را پیاده سازی نمایید. شما در گام اول 2 نوع تلفن همراه را شناسایی نموده‌اید (Android و Windows Phone). پس از شناسایی، احتمالا هر کدام از این انواع را یک کلاس در نظر می‌گیرید و به کمک یک واسط یا کلاس انتزاعی، شروع به ساخت کلاس می‌نمایید، تا در آینده اگر تلفن همراه جدیدی شناسایی شد، راحت‌تر بتوان آن را در پیاده سازی دخیل نمود.اگر چنین فکر کرده اید باید گفت که 90% با الگوی طراحی Builder آشنا هستید و از آن نیز استفاده می‌کنید؛ بدون اینکه متوجه باشید از این الگو استفاده کرده‌اید. ادامهبه کارگیری الگوی طراحی سازنده در طراحی نرم افزارها، با افزایش انعطاف پذیری و خوانایی کدها همراه خواهد بود. البته از طرفی دیگر پیاده سازی این الگو نیازمند ساخت چندین کلاس و تابع اضافه است. الگوی طراحی سازنده در موارد زیر کاربردی خواهد بود :1- امکان ساخت نمونه‌های مختلفی از یک شی را فراهم می‌سازد (برای مثال خانه‌های چوبی، سنگی و...).2- باعث جلوگیری از ساخت تعداد زیادی Constructor برای ساخت اشیا می‌شود.3- ساخت اشیای پیچیده و مرکب را ساده‌تر می‌کند. ادامهبیشترالگوهای رفتاری behavioralالگوهای structural و creational بر روی ایجاد اشیا متمرکز بودند. اما در الگوهای رفتاری به الگوریتم ها، مبادله ی اطلاعات و رفتار کلاس ها توجه میشود.این الگوها نحوه بیان تقسیم عملیات بین کلاس ها را تعریف کرده و چگونگی ارتباط بین آنها را بهبود میدهند.StrategyStateTemplate MethodChain of ResponsibilityCommandIteratorMediatorObserverVisitorInterpreterMementoهدف الگوی Strategyتعریف interface بیرونی یک الگوریتم به شکل انتزاعی به منظور فراهم کردن پیاده سازی آن به شکل های مختلف.اگر بخواهیم یک مثال ساده از الگوی Strategy بزنیم می توانیم برنامه ای را مثال بزنیم که با استفاده از روش های متفاوت مرتب سازی یک سری اعداد را مرتب سازی می کند. الگوریتم های متفاوتی برای مرتب سازی وجود دارد که می توان به QuickSort و یا MergeSort اشاره کرد. هرکدام از این روش ها می توانند در شرایط خاصی بهترین انتخاب موجود باشند. می توان تصمیم گیری این شرایط را با استفاده از الگوی Strategy پیاده سازی نمود. به این شکل که یک مجموعه از ورودی ها را داریم. ولی هرکدام از روش های مرتب سازی را به صورت جداگانه پیاده سازی می کنیم. ولی ورودی ها و خروجی ها ی یکسانی داشته باشند. در این صورت با توجه به شرایط ورودی ها را به یک الگوریتم داده و خروجی آن را دریافت خواهیم کرد. ادامهبرای مثال فرض کنید که ما در حال طراحی یک برنامه مسیریابی برای یک شبکه هستیم. همانطوریکه می‌دانیم برای مسیر یابی الگوریتم‌های مختلفی وجود دارد که هر کدام دارای مزایا و معایبی هستند. و با توجه به وضعیت موجود شبکه یا عملی که قرار است انجام پذیرد باید الگوریتمی را که دارای بالاترین کارائی است انتخاب کنیم. همچنین این برنامه باید امکانی را به کاربر بدهد که کارائی الگوریتم‌های مختلف را در یک شبکه فرضی بررسی کنید. حالا طراحی پیشنهادی شما برای این مسئله چست؟دوباره فرض کنید که در مثال بالا در بعضی از الگوریتم‌ها نیاز داریم که گره‌های شبکه را بر اساس فاصله‌ی آنها از گره مبداء مرتب کنیم. دوباره برای مرتب سازی الگوریتم‌های مختلف وجود دارد و هر کدام در شرایط خاص، کارائی بهتری نسبت به الگوریتم‌های دیگر دارد. مسئله دقیقا شبیه مسئله بالا است و این مسله می‌توانند دارای طراحی شبیه مسله بالا باشد. پس اگر ما بتوانیم یک طراحی خوب برای این مسئله ارائه دهیم می‌توانیم این طراحی را برای مسائل مشابه به کار ببریم.هر کدام از ما می‌توانیم نسبت به درک خود از مسئله و سلیقه کاری، طراح‌های مختلفی برای این مسئله ارائه دهیم. اما یک طراحی که می‌تواند یک جواب خوب و عالی باشد، الگوی استراتژی است که توانسته است بارها و بارها به این مسئله پاسخ بدهد.الگوی استراتژی گزینه مناسبی برای مسائلی است که می‌توانند از چندین الگوریتم مختلف به مقصود خود برسند.ادامهبیشترهدف الگوی Stateفراهم کردن قابلیت تغییر رفتار برای یک شی در حالت های مختلف وضعیت آن.یک برنامه پرواز را در نظر بگیرید که توسط یک شرکت هواپیمایی استفاده می شود. کار این برنام به این شکل است که هر مسافر که برای اولین بار برای پرواز به این شرکت می آید در وضعیت آبی قرار دارد. سیستم برای مسافران وضعیت آبی امکانات و تسهیلات خاصی در نظر می گیرد. و قیمت پرواز را برای آنان به گونه ای حساب می کند که تخفیف ندارد و همچنین مسافت پروازی آنان نیز محدود است. بعد از 5 پرواز که همان مسافر با این شرکت هواپیمایی انجام داد و پروازش در این سیستم ثبت شد مسافر از وضعیت آبی به وضعیت نقره ای ارتقاع پیدا می کند. سیستم برای مسافران وضعیت نقره ای برای هر پرواز 5 درصد تخفیف در نظر می گیرد و همچنین مسافت پرواز را به اندازه ای افزایش می دهد. حال اگر شخصی بیش از 15 پرواز انجام داده باشد به وضعیت طلایی خواهد رسید و برای هر پرواز 15 درصد تخیفیف خواهد گرفت. دقت کنید که مسافر باید این پرواز ها را در طول یک سال انجام دهد. حال وضعیت مسافر را توسط الگوی State پیاده سازی می کنیم. در الگوی State رفتار کلاس با توجه به حالت (State) کلاس تغییر می کند. این الگو یک الگوی رفتاری است. در این الگو ما اشیائی را می سازیم که حالت های مختلف یک کلاس را دارا می باشد.این الگو برای پیاده سازی ابزارهای گرافیکی مورد استفاده قرار بگیرد و در کل برای اشیائی که باید در زمان اجرا تغییر کند. همچنین برای اشیایی که در حال پیچیده شدن هستند و شرط های زیادی دارند قابل استفاده است. ادامهبیشترهدف الگوی Template Methodاسکلت کلی یک الگوریتم را تعریف کرده و این امکان را فراهم میکند که بدون تغییر ساختار کلی الگوریتم بتوان برخی از مراحل آن را به زیر کلاس ها سپرد.سناریویی وجود دارد که در آن شما می‌خواهید تنها یک کار را انجام دهید، ولی برای انجام آن n روش وجود دارد. برای مثال قصد مرتب سازی دارید و برای اینکار روش‌های مختلفی وجود دارند. برای حل این مساله پیشتر از الگوی طراحی استراتژی استفاده نمودیم.حال به سناریویی برخورد کردیم که بصورت زیر است:می‌خواهیم یک کار را انجام دهیم ولی برای انجام این کار تنها برخی بخش‌های کار با هم متفاوت هستند. برای مثال قصد تولید گزارش و چاپ آن را داریم. در این سناریو خواندن اطلاعات و پردازش آن‌ها رخدادهایی ثابت هستند. ولی اگر بخواهیم گزارش را چاپ کنیم به مشکل می‌خوریم؛ چرا که چاپ گزارش به فرمت اکسل، فرمت و روش خود را دارد و چاپ به فرمت PDF شرایط خود را دارد.در این سناریو دیگر الگوی طراحی استراتژی جواب نخواهد داد و نیاز داریم با یک الگوی طراحی جدید آشنا بشویم. این الگوی طراحی Template Method نام دارد. ادامهبیشترهدف الگوی Chain of Responsibilityشکستن اتصال مستقیم درخواست دهنده به کسی که درخواست را سرویس میدهد با ایجاد زنجیره ای از اشیا سرویس دهنده که یکی پس از دیگری بر حسب اولویت برای پاسخگویی به درخواست ، تلاش کرده و اگر قادر به سرویس دهی درخواست نباشید این مسئولیت را به شی بعدی زنجیره ارجاع می دهند.سناریوی گرفتن وام دانشجویی را در نظر بگیرید؛ به این صورت که دانشجو وارد سامانه شده، رمز خود یا شماره دانشجویی خود را زده و درخواست خود را ثبت می‌کند و پاسخی را از سیستم دریافت میکند. فرض کنید سلسله مراتب سیستم به این صورت باشد که ابتدا بررسی میکند که دانشجو فعال باشد. مرحله بعد رمز دانشجو صحیح باشد. مرحله بعد اینکه مقدار وامی که قبلا گرفته است، از حداکثر وام ثبت شده در سیستم بیشتر نباشد و مرحله آخر هم ثبت درخواست وام.اولین راه حلی که به ذهن میرسدif elseswitch caseبله مورد اولی که به ذهن خود من رسید، استفاده از if else هست. شاید خروجی مناسبی را از نظر کدنویسی داشته باشد؛ ولی خوانایی مناسبی را ندارد. حالا چطور اثبات کنیم خوانایی و قابلیت توسعه‌ی پایینی را دارد؟فرض کنید شما برنامه را نوشته‌اید و تحویل مدیر خود داده‌اید. بعد از دو ماه به شما گفته می‌شود که مراحل 1 و 2 را جابجا کنید و یا یک step را اضافه کنید که بعد از مرحله دو (بررسی رمز) است تا یک منطق جدید را دنبال کند. اینجاست که دچار دردسر و اتلاف زمان میشویم؛ چون باید بیزینس را مجددا review کنیم و بدتر از آن کدها را هم تغییر دهیم که امکان رخ دادن خطا به شدت بالا می‌رود. ادامهبیشترهدف الگوی Commandفاصله انداختن بین درخواست دهنده و گیرنده ی درخواست با ذخیره کردن درخواست ها به شکل شی و فراهم کردن قابلیت هایی مانند Undo،Rendo ،لاگ گیری از فعالیت کاربر، اسکریپت نویسی و مانند آن.لگوی Command در سیستم منو های بسیاری از برنامه های معروف استفاده می شود. در بسیاری از نرم افزار هایی که امروزه با آنها سرو کار داریم منویی به نام Edit دارند که اعمال کپی و کات کردن را داخل منوی Edit دارند و از طرفی هم همان اعمال کپی و کات کردن در داخل نوار ابزار بالای صفحه نیز موجود می باشد. این به این معنی است که هر دوی آنها یک عمل را انجام می دهند. و این اعمال دارای قابلیت Undo نیز می باشند. همه ی این اعمال کاربرد های الگوی Command می باشد. ادامهبیشترهدف الگوی Iteratorفراهم کردن راهی که طی آن بتوان عناصر یک شی انجمنی(aggregate object) مانند یک لیست یا مجموعه ای از داده ها را بدون آگاهی از ساختار آن یا بر ملا کردن محتویات آن یکی پش از دیگری پردازش کرد.فرض کنید قبلا کلاسی بنام CollectionClass را داشته‌اید که در آن یک آرایه از نوع []String تعریف کرده‌اید. همچنین n تا کلاس هم دارید که از آرایه‌ی تعریف شده‌ی در CollectionClass استفاده می‌کنند. تا اینجا مشکلی نیست. مشکل زمانی شروع می‌شود که متوجه می‌شوید دیگر این آرایه کارآیی ندارد و باید آن را با <List<string جایگزین کنید. واضح است که نمی‌توانید همه کلاس‌هایی را که از CollectionClass استفاده کرده‌اند، بیابید و آنها را تغییر دهید؛ چرا که شاید برخی از کلاس‌ها اصلا در دسترس شما نباشند یا هر دلیل دیگری.راهگشای این مشکل، استفاده از الگوی طراحی Iterator است. در این الگو، باید کلاس CollectionClass ابتدا واسط IEnumerable را پیاده سازی نماید. این واسط متدی بنام GetEnumerator دارد که می‌توان به کمک آن، درون آرایه یا هر نوع کالکشن دیگری حرکت کرده و آیتم‌های آن را برگرداند.ادامهاز این الگو در موارد زیر استفاده می شود:برای دسترسی به محتوای یک شئ تجمعی بدون در نظر گرفتن ساختار داخلی آن.برای پیمایش در اشیا تجمعی(هر گاه هر شی خود دارای زیر گروه هایی از اشیا باشد و بخواهیم به همه آن ها دسترسی داشته باشیم.)برای فراهم کردن یک واسط یکتا برای پیمایش ساختار های تنوعی متفاوت. ادامهبیشترهدف الگوی Mediatorتعریف شی واسطه برای جلوگیری از ارتباط مستقیم اشیا مختلف به یکدیگر و مدیریت روابط بین آنها.برج مراقبت یک فرودگاه را در نظر بگیرید. این بخش از تمامی هواپیماهایی که تردد میکنند باخبر بوده و وظیفه مدیریت پرواز آن ها را بر عهده داشته و اجازه فرود و پرواز آن ها را صادر میکند. در صورتی که اجازه فرود داده نشود ، هواپیما اجازه به نشستن ندارد. ادامهبیشترهدف الگوی Observerبین یک شی و تعدادی شی دیگر رابطه یک-به-چند تعریف میکند به گونه ای که وقتی شی نخست تغییر میکند وقوع تغییر را به اشیا مرتبط با خود اعلام میکند تا آنها به دنبال آن کاری را به تناسب انجام بدهند.یک لامپ و سوئیچ برق را درنظر بگیرید. زمانیکه لامپ مشاهده می‌کند سوئیچ برق در حالت روشن قرار گرفته‌است، روشن خواهد شد و برعکس. در اینجا به سوئیچ، subject و به لامپ، observer گفته می‌شود. هر زمان که حالت سوئیچ تغییر می‌کند، از طریق یک callback، وضعیت خود را به observer اعلام خواهد کرد. علت استفاده از callbackها، ارائه راه‌حل‌های عمومی است تا بتواند با انواع و اقسام اشیاء کار کند. به این ترتیب هر بار که شیء observer از نوع متفاوتی تعریف می‌شود (مثلا بجای لامپ یک خودرو قرار گیرد)، نیازی نخواهد بود تا subject را تغییر داد.عموما به شیءایی که قرار است وضعیت را مشاهده یا رصد کند، Observer گفته می‌شود و به شیءایی که قرار است وضعیت آن رصد شود Observable یا Subject گفته می‌شود. ادامهفرض کنید شما علاقه مند به اخبار ورزشی هستید. برای دنبال کردن اخبار ورزشی، یک مجله معتبر و خوب پیدا می‌کنید. در اشتراک ماهانه/هفتگی آن مجله عضو می‌شوید. با اینکار، هر بار که مجله فوق شماره جدیدی چاپ کند، موظف است این نسخه جدید را برای شما ارسال کند. در نتیجه این نسخه جدید برای شما ارسال می‌شود و شما قادر خواهید بود تا اخبار ورزشی جدید را در این شماره پیدا کنید. اما این چرخه تا کی ادامه خواهد داشت؟ مسلما تا زمانی که شما اشتراک ماهانه/هفتگی را تمدید کنید. پس اگر اشتراک خود را تمدید نکنید و یا بصورت داوطلب انصراف دهید، دیگر نسخه‌های جدید مجله برای شما ارسال نخواهد شد.الگوی طراحی Observer در واقع پیاده سازی ایده‌ی فوق است. در این الگو کلاس مورد نظر ما یک لیست از اعضا دارد. بخش‌های دیگر برنامه می‌توانند در این لیست عضو شوند. در صورتی که تغییری در کلاس ما اتفاق بیوفتد، این تغییر به همه اعضای لیست اعلام خواهد شد. اعضا در واقع هر بخشی از برنامه است که می‌خواهد تغییری را در کلاس ما نظارت کند. به عنوان یک مثال کاربردی فرض کنید دو موجودیت مشتری و فروشگاه داریم. یکی از مشتری‌ها به یک برند خاص(مثلا اپل) خیلی علاقه دارد و هر روز برای اینکه بداند مدل جدید گوشی این برند در فروشگاه موجود است یا خیر، به فروشگاه سر می‌زند. ادامهبیشترهدف الگوی Visitorساده سازی اجرای یک عملیات بر روی مجموعه ای از اشیا ناهمگون که مفهوم و ماهیت آن عملیات به طور کلی ثابت است اما هر شی ، آن را به شکل متفاوتی انجام می دهد.این الگو یکی دیگر از الگوهای رفتاری است که به قاعده OCP یا Open Closed Principle کمک بسیاری می‌کند. این الگو برای زمانی مناسب است که ما سعی بر این داریم تا یک سری الگوریتم‌های متفاوت را بر روی یک سری از اشیاء پیاده سازی کنیم. به عنوان مثال تصور کنید که ما در یک سازمان افراد مختلفی را از مدیریت اصلی گرفته، تا ساده‌ترین کارمندان، داریم و برای محاسبه حقوق و مالیات و ... نیاز است تا برای هر کدام دستور العمل‌هایی را اجرا کنیم و ممکن است در آینده تعداد این دستور العمل‌ها بالاتر هم برود. ادامهبیشترهدف الگوی Interpreterتعریف قوانین یک زبان به صورت شی گرا برای بیان جملات زبان و فراهم کردن مفسری که بتواند جملات زبان را تفسیر کند.بیشتر !هدف الگوی Mementoذخیره سازی وضعیت شی در یک منبع خارجی به منظور احیا وضعیت آن در آینده بدون آن که اطلاعات خصوصی شی بر ملا شده یا از خصلت کپسوله سازی و پنهان سازی اطلاعات تخطی شود.همه ی نرم افزارهای مدرن امروزه از قابلیتی به نام Undo استفاده می نمایند. این قابلیت به این صورت است که اگر ما کاری را در یک نرم افزار انجام داده باشیم و بخواهیم که برنامه این عمل ما را نادیده فرض کنید از این قابلیت استفاده می نماییم. و برنامه را به حالت قبل از عمل برمی گرداند. به طور مثال اگر در یک برنامه واژه پرداز (word processor) متنی را نوشته باشیم یا متنی را به عمد و یا غیر عمد حذف کرده باشیم ولی از انجام آن پشیمان شویم از قابلیت undo استفاده می نماییم. همچنین در بازی های رایانه ای موجود وقتی به مرحله ی خاصی از بازی رسیدیم وضعیت بازی ذخیره می شود. که به هر قسمت ذخیره شده یک check point گفته می شود. ذخیره سازی وضعیت نرم افزار در برنامه گفته شده و check point بازی با استفاده از الگوی memento انجام می شود.اهداف این الگو1- بدون این که خللی در کپسوله سازی وارد کند حالت فعلی یک شی را دریافت و نگهداری می کند.2-حالت شی را بعد از این که ذخیره کرد هر وقت که نیاز داشته باشیم برمی گرداند. این ویژگی برای گرفتن Checkpoint و مکانیزم undo مفید است.ادامهبیشتربطور خلاصهالگوی Abstract Factory: خانواده هایی از اشیا که اعضای خانواده به یکدیگر مرتبط هستند را تولید می کند.الگوی Adapter: اینترفیسی ایجاد می کند که کلاس هایی که با هم مرتبط نیستند بتوانند با یکدیگر کار کنند.الگوی Bridge: جدا ساختن قسمت پیاده سازی از قسمت انتزاعی یک کلاس برای این که دو طرف بتوانند به راحتی و مستقلا تغییر کنند.الگوی Builder: ساخت يک شی پيجيده را به گونه اي از نمايش آن مجزا مي کند که همان فرآيند ساخت مي تواند نمایش های متفاوتی ایجاد کند.الگوی Chain of Responsibility: در قالب یک زنجیره از اشیا به درخواست کاربر پاسخ می دهد.الگوی Command: مشخص می کند که یک عملیات(operation) چگونه انجام شود و انجام آن ها را مدیریت می کند.الگوی Composite: اشیا را در ساختارهاي درختي ترکيب مي کند. Composite به کاربران اجازه مي دهد با اشیا منفرد و اشیا ترکيبي به طور يکسان برخورد کنند.الگوی Decorator: مسؤوليت هاي اضافي را به طور ديناميک به يک شی ضميمه مي کند . Decorator ها جايگزيني انعطاف پذير جهت طبقه بندي فرعي براي توسعه عملکرد مهيا مي کنند .الگوی Facade: اینترفیسي يکنواخت براي مجموعه ميانجي هاي موجود در يک کلاس فرعي مهيا مي کند . نماي خارجي، اینترفیس سطح بالاتري را تعريف مي کند که استفاده از سيستم فرعي را ساده تر مي کند .الگوی Factory Method: يک اینترفیس جهت ايجاد يک شی تعيين مي کند ، ولي اجازه مي دهد کلاس هاي فرعي تصميم بگيرند کدام کلاس را معرفي کندالگوی Flyweight: زمانی استفاده می شود که تعداد اشیا بسیار زیاد باشد و مدیریت آنها سخت باشد.الگوی Interpreter: جهت تعریف گرامرهای یک زبان و تفسیر جملات استفاده می شود که تنها در طراحی کامپایلرها کاربرد دارد.الگوی Iterator: شيوه اي جهت دسترسي به عناصر يک شی بهم پيوسته به طور متوالي تدارک مي بيند بدون اين که نمايش موجود را دچار مخاطره کند .الگوی Mediator: شیئی را تعيين مي کند که چگونگي تعامل يک مجموعه اشیا را در یک محفظه قرار مي دهد. همچنین باعث می شود که اشیا به طور دو به دو کمتر با هم ارتباط داشته باشند و پدیده ی coupling کمتر شود.الگوی Memento: حالت دروني يک شی را به گونه اي دقيق ذخیره می کند که بعدا بتوان شی را به اين حالت بازگرداند.الگوی Observer: يک وابستگي يک به چند ميان اشیا را به گونه اي تعريف مي کند که هنگامي که يک شی تغيير کند کليه موارد وابسته به آن متوجه شده و به طور خودکار بهنگام سازي شوند .الگوی Prototype: برای ساخت و کپی کردن شیئی جدید که خواص شی اصلی را داشته باشد.الگوی Proxy: براي شی ديگر يک جانشين يا جاي گيرنده فراهم مي کند تا چگونگي دسترسي به آن را کنترل کند .الگوی Singleton: تضمين مي کند که يک کلاس فقط يک نمونه داشته باشد ، و يک نمونه ي کلي جهت دسترسي به آن را مهيا کند .الگوی State: به يک شی اجازه مي دهد هنگامي که حالت دروني آن تغيير کرد رفتار خود را عوض کند . به نظر مي رسد که شی کلاس خود را عوض مي کند .الگوی Strategy: يک خانواده از الگوريتم ها را تعريف کرده ، هر يک را در پوشش قرار داده و آن ها را قابل تعویض مي سازد . استراتژي اجازه مي دهد الگوريتم به طور مستقل از کاربران که از آن استفاد مي کنند متفاوت باشد .الگوی Template Method: اسکلت بندي الگوريتم در يک عمليات را تعريف کرده ، پیاده سازی بعضي مراحل را یه کلاس های فرعی می سپارد. همچنین به کلاس هاي فرعي مجال مي دهد بعضي مراحل يک الگوريتم را بدون تغيير ساختار الگوريتم دوباره تعريف کند .الگوی Visitor: ويزيتور به شما مجال مي دهد عمليات جديد را بدون تغيير کلاس هاي عناصري که در آن کار مي کند تغيير دهيد .منبع این بخش https://virgool.io/@espiar/%D9%85%D9%82%D8%AF%D9%85%D9%87-design-patterns-y8ypfllrygl5 کلام آخر اینکه باز این الگو ها رو می توان با هم ترکیب کرد برای اطلاعات بیشتر کتاب الگو های طراحی در C# 5 بخوانید (نسخه سی شارپش خیلی قدیمی هست با سی شارپ جدید می تواند الگوها را طوری دیگر پیاده کرد)منبع عکس ،در عکس آورده شده است