<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های امین احسان</title>
        <link>https://virgool.io/feed/@AminEhsan</link>
        <description>مجموعه مقالات با هدف تحلیل و بررسی علوم کامپیوتر</description>
        <language>fa</language>
        <pubDate>2026-04-15 07:01:22</pubDate>
        <image>
            <url>https://static.virgool.io/images/default-avatar.jpg</url>
            <title>امین احسان</title>
            <link>https://virgool.io/@AminEhsan</link>
        </image>

                    <item>
                <title>اصول SOLID در برنامه نویسی</title>
                <link>https://virgool.io/@AminEhsan/solid-principles-c2u8rzdchdma</link>
                <description>SOLID Principlesبررسیکلمه SOLID مخفف پنج اصل در برنامه‌نویسی و طراحی شی‌گرا می‌باشد.وقتی با پیروی از این اصول، برنامه‌ها طراحی و پیاده‌سازی می‌شود، باعث ایجاد قابلیت توسعه و نگهداری در آن‌ها خواهد شد.اصول SOLID دستورالعمل‌هایی هستند که با پیروی از آن‌ها، می‌توان قابلیت نگهداری، قابلیت فهم و انعطاف پذیر ایجاد کرد. در نتیجه، باعث کاهش پیچیدگی‌ها و وابستگی‌های سیستم می‌شود.Single Responsibility Principleاصل یگانگی مسئولیتطبق این اصل، یک کلاس باید تنها دارای یک وظیفه واحد باشد و در ادامه فقط باید یک دلیل برای تغییر یا بازنویسی آن وجود داشته باشد.کلاسی، در یک نرم‌افزار وظیفه نمایش گزارش‌های متنی را دارد. این کلاس، به دو دلیل ممکن است شامل تغییر شود:محتوای متن گزارش‌ها تغییر کند.قالب نگارش گزارش‌ها تغییر کند.اصل Single Responsibility می‌گوید، که این دو تغییر دارای دو مسئولیت جداگانه می‌باشند. (دو جنبه از مشکل در واقع دو مسئولیت جداگانه است) بنابراین باید در کلاس‌های جداگانه قرار گیرند. قرار دادن دو مسئولیت متفاوت که در زمان‌های مختلف تغییر می‌یابند. در یک واحد نرم‌افزاری یک طراحی نامناسب به شمار می‌رود.برای اعمال این اصل باید، مسئولیت‌های هر کلاس را در نظر گرفت. و اگر دارای بیش از یک مسئولیت باشند، این مسئولیت‌های اضافی را به بخش‌های دیگر منتقل نمود.Open - Closed Principleاصل باز - بستهطبق این اصل، موجودیت‌ها یک نرم‌افزار (کلاس‌ها، ماژول‌ها) باید برای توسعه باز باشند ولی در برابر اعمال اصلاحات بسته باشند. این موجودیت‌ها باید به شکلی طراحی شوند که قابل توسعه باشد، بدون اینکه تغییری در کد منبع، ایجاد شود.باز باشند  به این معنی است که، ما باید بتوانیم ویژگی‌ها یا اجزای جدیدی را بدون تغییر در کد اصلی به برنامه اضافه کنیم.بسته باشند  به این معنی است که، ما نباید تغییرات احتمالی را، به شکل قطعی در کد اصلی ایجاد کنیم. زیرا این امر شما را در هنگام تغییر مجبور به بازنویسی کدها می‌کند.به عبارت ساده‌تر، این به معنای ایجاد موجودیت‌های نرم‌افزاری به شکلی است که، رفتار آنها بدون نیاز به ویرایش مجدد کدهای اصلی قابل تغییر باشد.فرض کنید، کلاسی، محتوایی را در فایلی ذخیره می‌کند. اما نام آن فایل به صورت داخلی در کدهای آن ثبت شده است. اگر زمانی نام فایل هدف تغییر کند، برای عملکرد صحیح، باید محتوای کدهای داخل کلاس بازنویسی شود، اما اگر نام فایل به عنوان یک پارامتر، از کلاینت قابل دریافت بود، (برای توسعه باز) می‌توانستیم رفتار را بدون تغییر کد منبع ویرایش کنیم. (برای اصلاح بسته)Liskov Substitution Principleاصل جانشینی لیسکوفطبق این اصل، بخش‌های مشتق شده یا کلاس‌های فرزند، باید بتوانند جایگزین بخش‌های پایه یا کلاس‌های پدر خود شوند.اصل Liskov Substitution تضمین می‌کند که هر کلاسی که فرزند یک کلاس پدر باشد، باید بتواند به جای پدر خود بدون هیچ رفتار غیر منتظره‌ای مورد استفاده قرار گیرد.در مثال، وقتی شغل اجدادی خانواده‌ای کشاورزی باشد، پسر خانواده، باید مهارت‌های کشاورزی را از پدرش به ارث برده و در صورت نیاز بتواند جایگزین پدرش شود.اگر پسر بخواهد شغل دیگری را ادامه دهد، و رفتار متفاوت داشته باشد، قطعا نمی‌تواند جایگزین پدرش شود، حتی با توجه به این که هر دو به یک خانواده و سلسله مراتب تعلق دارند.یکی از نمونه‌های دیگر این اصل، کلاس مستطیل است. (ارتفاع و عرض مستطیل می‌تواند هر مقدار باشد) اما (مربع، مستطیلی با عرض و ارتفاع برابر است)بنابراین گفته می‌شود که، می‌توانیم ویژگی‌های کلاس مستطیل را به کلاس مربع گسترش دهیم. (از کلاس مستطیل، برای کلاس مربع ارث‌بری کرد)برای انجام این کار، باید کلاس فرزند را با گسترش کلاس پدر به شکلی باز نویسی کنید تا با تعریف مربعی که چهار ضلع برابر دارد مطابقت داشته باشد.اما با انجام این کار نمی‌توان هر زمان کلاس فرزند (مربع) را با کلاس پدر (مستطیل) جایگزین کرد.پس با این کار، اصل Liskov Substitution را نقض می‌شود.(بنابراین صحیح نیست که برای تعریف کلاس مربع از کلاس مستطیل، ارث‌بری کرد)Interface Segregation Principleاصل تفکیک رابط‌هااین اصل بیان می‌کند که، هیچ کلاسی را نباید مجبور به پیاده سازی رابطی (Interface) کرد که، دارای بخش‌های بدونه استفاده برای آن باشد.هدف اصلی، تمرکز بر اجتناب از Interface های بزرگ با مسئولیت‌های پراکنده و متفاوت است. همچنین این اصل باعث اولویت دادن به Interface های کوچک با مسئولیت‌های خاص و مشخص می‌گردد.فرض کنید شما کاملا گیاهخوار هستید، وارد یک رستوران شدید. گارسون به شما، لیستی شامل همه اقلام گیاهی، غیر گیاهی، نوشیدنی‌ها و … را می‌دهد. شما در انتخاب با مشکل روبرو خواهید شد.بهتر است ،رستوران برای مشتریان کاملا گیاهخوار، دارای یک منو که فقط شامل اقلام گیاهی هست باشد، نه هر چیزی قابل سفارش.منوها باید برای انواع مختلف مشتریان متفاوت طراحی شوند. (منو که شامل همه اقلام مشترک برای تمام افراد باشد را می‌توان به چند زیر منو تقسیم کرد.اصل Interface Segregation باعث ایجاد گسستگی بخش‌ها در سیستم می‌شود، به طریقی که اصلاح، تغییر و انتشار مجدد کدها آسان‌تر خواهد گشت.Dependency Inversion Principleاصل وارونگی وابستگیطبق این اصل:ماژول‌ها یا کلاس‌های سطح بالا نباید به ماژول‌ها یا کلاس‌های سطح پایین وابسته باشند.هر دو در هر سطح باید به انتزاع (Abstract) وابسته باشند.اگر یک ماژول یا کلاس سطح بالا به ماژول‌ یا کلاس‌ سطح پایین وابسته باشد، کد شما جفت شدگی خواهد داشت. و اگر بخواهید در یک کلاس تغییری ایجاد کنید، می‌تواند باعث ایجاد مشکل در کلاس دیگر شود.انتزاع‌ها نباید به جزئیات وابسته باشند.جزئیات باید به انتزاع‌ها وابسته باشد.اصل Dependency Inversion به این معنا است که، بجای اینکه ماژول‌های سطح پایین Interface های قابل استفاده را در اختیار سطوح بالاتر سیستم قرار دهند، ماژول‌های سطح بالا، Interface های مورد پذیرش را تعریف می‌کنند که، توسط ماژول‌های سطح پایین پیاده‌سازی می‌شوند.در مثال باتری کنترل تلویزیون را در نظر بگیرید. کنترل تلویزیون به باتری نیاز دارد، اما نه فقط از یک برند یا مارک خاص. شما می‌توانید از هر برند و مارک که می‌خواهید استفاده کنید. (در نتیجه وابستگی کنترل تلویزیون در انتزاع از یک باتری می‌باشد نه جزئیات آن)این امر باعث ایجاد قابلیت استفاده مجدد از بخش‌های مختلف و همچنین بهبود توسعه پذیری می‌شود.linkedin.com/in/AminEhsangithub.com/AminEhsan</description>
                <category>امین احسان</category>
                <author>امین احسان</author>
                <pubDate>Fri, 20 Jan 2023 04:11:00 +0330</pubDate>
            </item>
                    <item>
                <title>الگوی طراحی سینگلتون - Singleton Design Pattern</title>
                <link>https://virgool.io/@AminEhsan/design-pattern-singleton-wjilodedbu4w</link>
                <description>Singleton Design Patternبررسیالگوی طراحی Singleton به شما امکان می‌دهد اطمینان حاصل کنید که یک کلاس فقط یک نمونه دارد، در حالی که یک اشاره‌گر سراسری برای دسترسی به این نمونه ارائه می‌کند.مشکلاین الگوی طراحی با نقض Single Responsibility Principle چند مشکل را همزمان حل می‌کند:اطمینان حاصل می‌کند که یک کلاس فقط یک نمونه از خود دارد، (رایج‌ترین دلیل این امر کنترل دسترسی به برخی از منابع مشترک است) مانند: پایگاه داده یا یک فایلنحوه کار به این صورت است. تصور کنید که یک شی ایجاد کرده‌اید اما پس از مدتی تصمیم به ایجاد یک شی جدید دارید، به جای دریافت یک شی تازه، نمونه‌ای را که قبلاً ایجاد کرده‌اید دریافت می‌کنید. توجه داشته باشید که اجرای این رفتار با یک Constructor معمولی غیرممکن است، چرا که بر اساس طراحی باید یک شی جدید را برگرداند.بنابراین یک نقطه دسترسی سراسری به آن نمونه یکتا وجود خواهد داشت. (اما متغیرهای سراسری در حالی که بسیار مفیدند، ناامن هم هستند) زیرا هر بخش از کد که در روند اجرای برنامه حضور دارد، می‌تواند محتوای آن متغیرها را بازنویسی و برنامه را خراب کند. الگوی Singleton به شما امکان می‌دهد از هر کجای برنامه به برخی از نمونه‌ها دسترسی داشته باشید، با این حال آن نمونه‌ها را از بازنویسی شدن توسط کدهای دیگر نیز محافظت می‌کند.این مشکل جنبه دیگری هم دارد. شما نمی‌خواهید کدی که مشکل را حل می‌کند در سراسر برنامه پخش شود، بنابراین بهتر است که آن را در یک کلاس قرار دهید. مخصوصا اگر بقیه کد شما از قبل به آن وابستگی داشته باشد.راه حلمتد Constructor پیش فرض را Private کنید تا دیگر اشیا از عملگر New استفاده نکنند. یک متد Static ایجاد کنید که به عنوان سازنده عمل کند. این متد از Constructor که Private شده برای ایجاد یک شی استفاده کرده و آن را در یک فیلد Static ذخیره می‌کند.همه فراخوانی‌های بعدی به این متد، شی ذخیره شده را برمی‌گرداند. بنابراین اگر کد شما به کلاس Singleton دسترسی دارد، می‌تواند متد سازنده جدید را فراخوانی کند. و هر زمان آن متد فراخوانی شود همان شی ذخیره شد در فیلد Static برگردانده خواهد شد.ساختارکلاس Singleton متد getInstance را به شکل static تعریف می‌کند که همان نمونه ساخته شده از کلاس خود را برمی‌گرداند. Constructor در Singleton باید از کد کلاینت پنهان باشد، فراخوانی متد getInstance باید تنها راه دریافت شی از کلاس Singleton بشود.نمونهدولت نمونه‌ای از الگوی Singleton است. یک کشور می‌تواند تنها یک دولت رسمی داشته باشد صرف نظر از هویت شخصی افراد تشکیل دهنده آن، عنوان دولت یک اشاره‌گر سراسری است که گروه افراد مسئول را، مشخص می‌کند.نتیجهاز الگوی Singleton زمانی استفاده می‌شود که یک کلاس در برنامه شما فقط باید دارای یک نمونه واحد قابل دسترس برای تمام کدها باشد. مانند یک شی واحد از پایگاه داده که توسط بخش‌های مختلف برنامه به اشتراک گذاشته شده است.این الگوی تمام ابزارهای دیگر برای ایجاد اشیا از یک کلاس را غیرفعال می‌کند، به جز روشی خاص، که یا یک شی جدید ایجاد می‌کند یا اگر قبلا ایجاد شده باشد، آن را بر می‌گرداند.زمانی که به کنترل دقیق تری بر روی متغیرهای سراسری نیاز دارید از الگوی Singleton استفاده کنید.الگوی Singleton تضمین می‌کند که، فقط یک نمونه از یک کلاس وجود دارد هیچ چیز به جز خود کلاس Singleton نمی‌تواند جایگزین نمونه ذخیره شده شود.توجه داشته باشید که همیشه می‌توانید این محدودیت را تنظیم کنید و اجازه ایجاد هر تعداد نمونه از Singleton را بدهید. تنها کدی که نیاز به تغییر دارد، بدنه متد نمونه‌گیر است.linkedin.com/in/AminEhsangithub.com/AminEhsan</description>
                <category>امین احسان</category>
                <author>امین احسان</author>
                <pubDate>Thu, 12 Jan 2023 16:35:34 +0330</pubDate>
            </item>
                    <item>
                <title>الگوی طراحی آداپتور - Adapter Design Pattern</title>
                <link>https://virgool.io/@AminEhsan/design-pattern-adapter-uxufi2tfjqs6</link>
                <description>Adapter Design Patternبررسیالگوی طراحی Adapter به اشیا با Interface‌ های ناسازگار اجازه همکاری می‌دهد.مشکلتصور کنید که در حال ایجاد یک برنامه نظارت بر بازار سهام هستید، این برنامه داده‌های سهام را از چندین منبع در قالب XML بارگیری می‌کند و سپس نمودارها و دیاگرام‌های زیبا را برای کاربر نمایش می‌دهد.در برخی مواقع تصمیم می‌گیرید با ادغام یک کتابخانه تحلیلی هوشمند (شخص ثالث) برنامه را بهبود ببخشید، اما یک نکته وجود دارد، کتابخانه فقط با داده‌ها در قالب JSON کار می‌کند.می‌توانید کتابخانه را برای کار با قالب XML تغییر دهید. با این حال این کار ممکن است برخی از کدهای موجود را که به کتابخانه متکی است خراب کند و بدتر از آن ممکن است به کدهای منبع کتابخانه دسترسی نداشته باشید که در این صورت تغییر دادن کتابخانه روشی غیر ممکن خواهد بود.راه حلمی‌توانید یک الگوی Adapter ایجاد کنید، این الگو Interface‌ یک شی را، به گونه‌ای تغییر می‌دهد که یک شی دیگر، بتواند آن را درک کند.در واقع Adapter بر روی یکی از اشیا، روکشی را قرار می‌دهد تا پیچیدگی تغییر را در پشت صحنه پنهان کند. (شی حتی از وجود این روکش آگاه نمی‌شود)برای مثال می‌توانید یک شی‌ را که بر حسب متر و کیلومتر کار می‌کند، با قرار دادن روکش Adapter طوری بپیچید که تمام داده‌ها به واحدهایی مانند فوت و مایل تبدیل شوند.آن‌ها نه تنها می‌توانند داده‌ها را به فرمت‌های مختلف تبدیل کنند، بلکه می‌تواند به همکاری و ارتباط اشیا با Interface‌ های مختلف کمک کنند.یک Interface‌ سازگار با یکی از اشیا موجود را دریافت می‌کند.با استفاده از این Interface‌ شی موجود می‌تواند، با خیال راحت متدهای Adapter را فراخوانی نماید. پس از دریافت فراخوانی، Adapter درخواست را به شی دوم ارسال می‌کند، اما در قالب و ترتیبی که شی دوم انتظار دارد.گاهی اوقات حتی می‌توان یک Adapter دو طرفه ایجاد کرد، که توانایی فراخوانی‌ها را در هر دو جهت در قالب مورد نظر را داشته باشد.بیایید به برنامه بازار سهام برگردیم، برای حل مشکل فرمت‌های ناسازگار می‌توانید، Adapter های XML-to-JSON را برای هر کلاسی از کتابخانه تحلیلی که کد شما مستقیما با آن کار می‌کند ایجاد کنید.سپس کد خود را، طوری تنظیم کنید که فقط از طریق این Adapter ها با کتابخانه ارتباط برقرار کنند.هنگامی که یک Adapter فراخوانی می‌شود، داده‌های XML ورودی را، به یک ساختار JSON تبدیل می‌کند و فراخوانی را به روش‌های مناسب تر به شی تحلیلگر ارسال می‌کند.ساختاربخش Client شامل Business Logic موجود در برنامه است.بخش Interface Client پروتکلی را توصیف می‌کند که سایر کلاس ها باید از آن پیروی کنند تا بتوانند با کد کلاینت همکاری کنند.بخشی Service معمولا ناسازگار (شخص ثالث یا قدیمی) که کلاینت نمی‌تواند مستقیما از این کلاس استفاده کند. (زیرا دارای یک Interface‌ ناسازگار است)بخشی Adapter می‌تواند با هر دو بخش دیگر کار کند. Interface‌ مشترک را پیاده سازی می کند و در حالی که شی Service را در بر گرفته است، درخواست‌ها را از طریق Interface‌ Adapter دریافت و آنها را به درخواست‌هایی که برای بخش دیگر قابل درک است ترجمه می‌کند.کد کلاینت تا زمانی که از طریق Interface‌ Client کار کند، با کلاس Adapter جفت نمی‌شود. که می‌توان به کمک آن انواع جدیدی از Adapter ها را بدون تغییر در کد کلاینت، به برنامه اضافه کرد. زمانی مفید است که Interface‌ Service تغییر کند. (شما فقط کافیست یک کلاس Adapter جدید بدون تغییر در کد Client ایجاد کنید)نمونههنگامی که برای اولین بار از کشوری به کشور دیگر سفر می‌کنید، ممکن است هنگام تلاش برای شارژ لپ‌تاپ خود غافلگیر شوید، استانداردهای پریز برق در کشورهای مختلف متفاوت است. اما مشکل را می‌توان با استفاده از یک Adapter برقی که دارای تبدیل سوکت می‌باشد حل کرد.نتیجهاز Adapter استفاده می‌شود، وقتی که می‌خواهید از یک کلاس موجود استفاده کنید، اما Interface‌ آن با بقیه کد شما سازگار نیست.الگوی Adapter به شما امکان می‌دهد یک کلاس لایه میانی ایجاد کنید که، به عنوان مترجم بین کد شما و (یک کلاس شخص ثالث) یا هر کلاس دیگری با Interface‌ متفاوت، عمل می‌کند.هنگامی که می‌خواهید چندین زیر کلاس موجود را که فاقد برخی عملکردهای مشترک هستند و نمی‌توانند به سوپر کلاس اضافه شوند، مجددا استفاده کنید، این الگو را به کار گیرید.شما می‌توانید هر زیر کلاس را گسترش دهید و عملکرد را در هر کلاس‌ فرزند جدید، قرار دهید. با این حال باید، کد را در تمام این کلاس‌ها کپی کنید، که اشتباه است. راه حل درست تر قرار دادن عملکردها در یک کلاس Adapter می‌باشد.سپس اشیا با عملکردهای نداشته را در داخل Adapter قرار می‌دهید تا عملکردهای مورد نیاز به صورت ‌Dynamic اضافه شوند. برای این کار کلاس‌های هدف باید یک Interface‌ مشترک داشته باشند و Adapter باید از آن Interface‌ پیروی کند. این رویکرد بسیار شبیه به الگوی Decorator است.linkedin.com/in/AminEhsangithub.com/AminEhsan</description>
                <category>امین احسان</category>
                <author>امین احسان</author>
                <pubDate>Thu, 12 Jan 2023 16:25:03 +0330</pubDate>
            </item>
                    <item>
                <title>الگوی طراحی دکوراتور - Decorator Design Pattern</title>
                <link>https://virgool.io/@AminEhsan/design-pattern-decorator-og7fgdeeihep</link>
                <description>Decorator Design Patternبررسیالگوی طراحی Decorator به شما امکان می‌دهد با قرار دادن شی‌ها در داخل فضایی با پوششی مخصوص که حاوی رفتارهای متفاوت هست، رفتارهای جدیدی را به شی‌ها ضمیمه کنید.مشکلتصور کنید روی یک کتابخانه ارسال اعلان کار می‌کنید که به برنامه‌های دیگر اجازه می‌دهد تا کاربران خود را در مورد رویدادهای مهم مطلع کنند.نسخه اولیه کتابخانه بر اساس کلاس Notifier است و فقط دارای چند فیلد (یک متد سازنده و یک متد ارسال) می‌باشد.این متد ارسال می‌تواند یک پیام را به‌عنوان آرگومان ورودی از کلاینت بپذیرد و آن را به لیستی از ایمیل‌هایی که از طریق سازنده این کلاس در اختیارش قرار گرفته ارسال کند.یک برنامه شخص ثالث که به‌عنوان کلاینت عمل می‌کند، قرار است یک شی از این کتابخانه را ایجاد و پیکربندی کند و هر بار که اتفاق مهمی رخ می‌دهد از آن استفاده نماید.در برخی مواقع متوجه می‌شوید که کاربران انتظار بیشتری از اعلان‌های دریافتی دارند، (بسیاری از آنها مایل به دریافت پیامک درباره موضوعات مهم هستند و برخی دوست دارند در شبکه اجتماعی اعلان‌ها را دریافت کنند)بنابراین شما کلاس Notifier را گسترش داده و روش‌های اعلان اضافی را در زیر کلاس‌های جدید قرار می‌دهید، بار دیگر کلاینت کلاس Notifier را نمونه‌سازی می‌کند تا از آن برای تمام اعلان‌های بعدی استفاده نماید و از روش‌های مختلف این اعلان‌ها را به کاربران برساند.اما پس از مدتی، از شما سوال خواهد شد که (چرا نمی‌توان به‌طور همزمان از چندین روش اعلان استفاده کرد) اگر خانه شما آتش‌گرفته است احتمالاً می‌خواهید از طریق هر کانال مطلع شوید.ولی شما سعی کردید با ایجاد زیر کلاس‌های خاص که چندین روش اعلان را در یک کلاس با هم ترکیب می‌کند به آن مشکل رسیدگی کنید. اما بااین‌حال به‌سرعت آشکار شد که این روش نه‌تنها کد کتابخانه بلکه کد کلاینت را نیز بسیار حجیم نموده و کارکرد کامل را ندارد.بنابراین شما باید روش دیگری برای ساخت کلاس‌های Notifier پیدا کنید.راه حلگسترش یک کلاس با کمک وراثت اولین چیزی است که وقتی باید رفتار یک شی را تغییر دهید به ذهن خطور می‌کند. اما وراثت دارای چندین نکته است که باید از آنها آگاه باشید:وراثت ایستا است شما نمی‌توانید رفتار یک شی موجود را در زمان اجرا تغییر دهید. فقط می‌توانید کل شی را با مورد دیگری که از یک زیر کلاس متفاوت ایجاد شده است جایگزین کنید.زیر کلاس‌ها در (اکثر زبانها) می‌توانند فقط یک کلاس والد داشته باشند. وراثت اجازه نمی‌دهد که یک کلاس رفتارهای چند کلاس را به طور همزمان به ارث ببرد.یکی از راه‌های غلبه بر این محدودیت‌ها استفاده از Aggregation یا Composition است.تجمع - Aggregation: شی A شامل اشیا B است B می‌تواند بدون A زندگی کند.ترکیب - Composition: شی A از اشیا B تشکیل شده است A چرخه زندگی B را مدیریت می‌کند B نمی‌تواند بدون A زندگی کند.هر دو روش جایگزین تقریباً به یک شکل کار می‌کنند:یک شی ارجاع به دیگری دارد و کاری را به آن محول می‌کند، در حالی که (با وراثت شی خود قادر به انجام آن کار است و رفتار را از کلاس والد خود به ارث می‌برد)با این رویکرد جدید می‌توانید به راحتی شی مرتبط را با دیگری جایگزین کنید و رفتار را در زمان اجرا تغییر دهید. یک شی می‌تواند از رفتار کلاس‌های مختلف استفاده کند و به چندین شی ارجاع داشته باشد و انواع کارها را به آنها واگذار کند.(تجمع / ترکیب اصل کلیدی پشت بسیاری از الگوهای طراحی از جمله Decorator است)نام مستعار جایگزین برای این الگو، Wrapper است، که به وضوح ایده اصلی الگو را بیان می‌کند. اینگونه که می‌تواند با دربرگرفتن، به شی هدف مرتبط شود. Wrapper شامل مجموعه‌ای از متدهای مشابه شی هدف است و تمام درخواست‌هایی را که دریافت می‌کند به آن می‌دهد با این حال ممکن است با انجام کاری (قبل یا بعد) از ارسال درخواست به هدف نتیجه را تغییر دهد.چه زمانی یک Wrapper ساده به الگوی Decorator واقعی تبدیل می‌شود؟همانطور که اشاره شد. Wrapper از همان Interface پیروی می‌کند که شی هدف (دربرگرفته شده) از آن پیروی می‌کند. به همین دلیل است که از منظر کلاینت این اشیا یکسان هستند (پس فیلد ارجاع Wrapper به شی هدف را باید طوری تغییر دهید که هر شی با پیروی از Interface مربوطه پذیرفته شود) با این کار می‌توان یک شی را در چندین Wrapper قرار داد و رفتار ترکیبی همه Wrapper را به آن اضافه نمود.در مثال Notifier اجازه دهید رفتار اعلان ایمیل را در کلاس پایه Notifier قرار دهیم اما سایر روش‌های اعلان را به Decorator تبدیل کنیم.کد کلاینت باید شی Notifier کننده اصلی را در مجموعه ای از Decorator ها قرار دهد که با ترجیحات کلاینت مطابقت دارد، سپس اشیا به دست آمده ساختار پشته خواهند داشت.آخرین Decorator در پشته، شیی است که در واقع کلاینت با آن کار می‌کند. از آنجایی که همه، Decorator Interface یکسانی را با Notifier اجرا می‌کنند، بقیه کد کلاینت اهمیتی نمی‌دهد که با شی Notifier که pure است کار میکند یا Decorat شده.ما می‌توانیم همین رویکرد را برای رفتارهای دیگر مانند قالب‌بندی پیام‌ها یا تهیه فهرست گیرندگان اعمال کنیم. کلاینت می‌تواند شی را با هر Decorator سفارشی Decorat کند. (به شرطی که از Interface مشابه پیروی داشته باشد)ساختاربخش Component همان Interface مشترک را برای (در برگیرنده) و (اشیا در برگرفته شده) مشخص می‌کند.بخش Concrete Component دسته‌ای از اشیا است که در برگرفته می‌شوند. (رفتار پایه را تعریف می‌کند که می‌تواند توسط Decorator ها تغییر یابد)بخش Base Decorator یک فیلد برای ارجاع به یک شی در برگرفته شده دارد. نوع فیلد باید نوع Interface تعریف شود تا بتواند حاوی Concrete Component و Decorator ها باشد. Base Decorator هم تمام عملیات را به شی در برگرفته شده واگذار می کند.بخش Concrete Component ها رفتارهای بیشتر را تعریف می‌کنند که می‌توانند به صورت پویا اضافه شوند. آن‌ها روش‌های Base Decorator را نادیده می‌گیرند و رفتار خود را قبل یا بعد از فراخوانی اجرا می‌کنند.کلاینت می‌تواند Component ها را در چندین لایه Decorat کننده، در برگیرد (تا زمانی که با همه اشیا از طریق Interface تعامل دارند)نمونهپوشیدن لباس نمونه‌ای از استفاده‌ Decorator ها می‌باشد.وقتی سردتان می‌شود لباس گرم می‌پوشید. اگر هنوز هم سردمان باشد می‌توانید یک ژاکت هم روی لباس‌هایتان بپوشید. یا اگر باران ببارد می‌توانید یک پالتوی بارانی بپوشید. همه این لباس‌ها رفتار اصلی شما را (گسترش می‌دهند) اما بخشی از شما نیستند، و هر زمان که نیازی به هر کدام از آن‌‌ها ندارید می‌توانید به راحتی هر لباس را از تن دربیاورید.نتیجهزمانی که بخواهید رفتارهای اضافی را به اشیا (در زمان اجرا) (بدون تغییر کدی که از این اشیا استفاده می‌کند) اختصاص دهید. باید از الگوی Decorator استفاده کنید.این الگو به شما این امکان را می‌دهد که منطق سیستم خود را لایه‌ لایه بسازید، و برای هر لایه یک Decorator ایجاد کنید، و در زمان اجرا اشیا را با ترکیبات مختلف از این منطق ساختارمند کنید. کد کلاینت می‌تواند با همه این اشیا به یک شکل رفتار کند، زیرا همه آنها از یک Interface مشترک پیروی می‌کنند.هنگامی که گسترش رفتار یک شی با استفاده از وراثت ممکن نیست، یا ناخوشایند است از Decorator استفاده می‌شود.بسیاری از زبان‌های برنامه‌نویسی کلیدواژه Final را دارند، که می‌توان از آن برای جلوگیری از گسترش بیشتر کلاس‌ها استفاده کرد. اما برای استفاده مجدد از رفتارهای این کلاس‌ها تنها راه، این است که آن‌ها را با در برگیرنده مخصوص با استفاده از الگوی Decorator در برگیریم.linkedin.com/in/AminEhsangithub.com/AminEhsan</description>
                <category>امین احسان</category>
                <author>امین احسان</author>
                <pubDate>Thu, 12 Jan 2023 16:11:32 +0330</pubDate>
            </item>
            </channel>
</rss>