وبلاگ طراحی و برنامه نویسی

پروژه - برنامه نویسی - گرافیک - انیمیشن - شبکه - پایگاه داده - مدار منطقی - کنکور

وبلاگ طراحی و برنامه نویسی

پروژه - برنامه نویسی - گرافیک - انیمیشن - شبکه - پایگاه داده - مدار منطقی - کنکور

الگو های طراحی (Design Pattern)

الگو های طراحی (Design Pattern) 

 

کسی وجود دارد که قبلاً مسله شما را حل کرده است.

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

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

 

تاریخچه الگو های طراحی :

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

هر الگو بیانگر یک مسئله و مشکل است که می تواند بارها و بارها روی بدهد همراه با راه حل آن مسئله، وشما می تواند از این راه حل برای میلیون ها بار استفاده کند بدون نیاز مجدد برای پیدا کردن راه حل.

در اوایل دهه 1990، بعضی از توسعه دهندگان نرم افزار با کارهای الگساندر برخورد کردند.آنها با این سوال روبرو شدند که اگر الگو های طراحی معماری در این رشته به صورت صحیح جواب می دهد آیا می توان الگوهای را برای طراحی نرم افزار بوجود آورد.

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

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

در اوایل دهه 1990، افرادی زیادی روی الگوهای طراجی کار می کردند. اما چهار نفر به نام های، گاما، جاکوبسون، هلم و ولسایدز بیشترین تاثیر را در این زمینه با نوشتن کتابی به نام

"Design Pattern: Elements of Reusable Object-Oriented Software"، داشتند. این چهار نویسنده به Gang of Four مشهور است. آنها در این کتاب ائده استفاده از الگوها را در طراحی نرم افزار به کار بردند.و یک فرمت استاندارد را برای مستندسازی الگوها ایجاد کردند. 23 نوع از الگوها را دسته بندی کردند و .... به مرور زمان فرمت های استاندارد دیگری برای مستند سازی الگوها پیشهناد شد.

 

 قالب مستند سازی برای الگوهای طراحی :

 

 

نام الگو

یک نام خوب و مفید برای الگو

هدف (intent)

یک جمله کوتاه و مختصر درباره چیزی که الگو انجام می دهد. (تعریف مسله و راه حل به صورت مختصر و مفید)

نام مستعار

نام های دیگری که الگو با آن شناخته می شود.

ساختار

یک نمایش گرافیکی از الگو

اجزاء تشکیل دهنده (Participants)

کلاس ها و اشیائ که در الگو شرکت دارند (وجود دارند).

همکاریها (Collaborations)

چگونه اجزای تشکیل دهنده با هم همکاری می کنند تا وظایفشان را انجام دهند.

نتایج‌ (Consequences)

نتایج استفاده از الگوی مورد نظر

پیاده سازی

تکنیک های برای پیاده سازی الگوی مورد نظر

نمونه کد

تکه کدی برای پیاده سازی یک نمونه

الگو های مرتبط

الگوهای طراحی دیگری که ارتباط نزدیگ با الگوی مورد نظر دارند.

 

دسته بندی الگو ها :

1-   الگوهای بوجود آورنده(Creational Pattern): همه الگو های که در این دسته قرار می کیرند در ارتباط با روش های ایجاد اشیاء هستند.

2-   الگوهای ساختاری(Structural Patten): این نوع الگوها شرح می دهند چگونه اشیاء و کلاس ها می توانند در ساختارهای بزرگتر باهم ترکیب شوند.

3-      الگوهای رفتاری(Behavioral Pattern): این نوع الگو ها روی ارتباط اشیاء با یکدیگر تمرکز دارند.

 

Creational

Structural

Behavioral

Factory Method

Abstract Factory

Builder

Prototype

Singleton

Adapter

Bridge

Composite

Decorator

Flyweight

Façade

Proxy

Interpreter

Template Method

Chain of Responsibility

Command

Iterator

Mediator

Memento

Observer

State

Strategy

Visitor




الگوی Flyweight


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

نام و نام خانوادگی

سمت

نام شرکت

آدرس

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

visitCard

Name

Title

Company

Address

print

در این صورت شما باید به ازاء هر کارمند یک نمونه از کلاس visitCard ایجاد کند، یعنی شما باید چند هزار شی visitCard ایجاد کند. و این می تواند منابع زیادی از سیستم را مصرف کند. ولی شما با توجه به ساختار کارت متوجه می شود که، نام شرکت و آدرس برای تمام افراد یکی است. با این آگاهی، آیا می خواهید تغییری در طراحی خود انجام بدهید یا نه؟

یا شما مسئول طراحی یک برنامه پردازش متن هستید. شکل زیر، می تواند یک نمودار کلاس ساده شده برای این برنامه باشد.

هر نمونه از کلاس Docchar نماینگر یک کاراگتر در سند است. برای تغییر فونت یک کاراگتر می توانیم متد SetFont از شی Docchar فراخوانی کنیم. اگر فونت یک کاراگتر مشخص نشده باشد، از فونت container خود استفاده خواهد کرد.

یک سند نمونه از این برنامه را با طراحی بالا در نظر بگیرید،  یک سند که شامل چندین صفحه است، هر  صفحه شامل چندین شی پارگراف خواهد بود، و هر پارگراف شامل چندین شی LineOfTextad   خواهد بود و آن نیز شامل صد ها شی DocChar خواهد بود، یعنی در یک سند چند صفحه ای ممکن است هزار ها شی  DocChar داشته باشیم که، حافظه زیادی را از سیستم مصرف خواهد کرد. شما برای کاهش مصرف حافظه، طراحی خود را به چه صورت تغییر می دهید؟

یک راه حل کاندید و خوب برای حل هر دو مسئله بالا، الگوی Flyweight است. که به بررسی آن خواهیم پرداخت. مشکل ما در هر دو مسئله بالا، تولید نمونه های بیش از حد از یک کلاس بود که منجر به مصرف زیاد منابع می شد. یک شی شامل 2 نوع اطلاعات است:

1-       اطلاعات داخلی (Intrinsic Information) : این نوع اطلاعات، اطلاعاتی هستند که برای تمام نمونه های یک کلاس ثابت است. برای مثال، نام شرکت و آدرس در مثال اول برای تمام کارمندان ثابت است.

2-       اطلاعات خارجی (Extrinsic Information) : این نوع اطلاعات، اطلاعاتی هستند که از نمونه ای به نمونه ای دیگر فرق می کند، یعنی اشیاء را از همدیگر متمایز می سازد. برای مثال، نام و سمت کارمند در مثال اول.

پیشنهاد الگوی Flyweight این است که،  اطلاعات خارجی را، به خارج از کلاس منتقل کنیم و این اطلاعات را به صورت پارامتر های ورودی متدها دریافت کنیم، و تعداد نمونه ها را با به اشتراک گذاری آنها کاهش دهیم. نمودار کلاس این الگو بصورت زیر است.

در نمودار بالا هر کدام از،ConcreteFlyweight ها نمونه های به اشتراک گذاری یک کلاس هستند. چون اشیاء به اشتراک گذاشته شده اند، Client ها نباید بطور مستقیم نمونه ای از آنرا ایجاد کنند. برای حل این مشکل، کلاس  FlyweightFactory را ایجاد می کنیم. این کلاس باید بداند که آیا نمونه ای از یک کلاس ایجاد شده است یا نه. برای این کار، لیستی از اشیاء ایجاد شده را نگهداری می کنیم  که این اشیاء از کلاس های مختلف توسط یک صفت کلید از هم متمایز می شوند. در مثال 2 ما برای حل مشکل خود برای هر کاراکتر، یک کلاس،تعریف می کنیم. کلید هر کدام از کلاس ها همان، کاراکتری است که نمایش خواهند داد. برای نمونه کلاس زیر را در نظر بگیرید، کلید هر کلاس را در  یک Hashtable ذخیره می کنیم، و وقتی که Client بخواهد نمونه ای از کلاس مورد نظرش را بسازد، این کلاس بررسی می کند که آیا این کلید در Hashtable وجود دارد یا نه. اگر وجو نداشته باشد، نمونه ای از کلاس مورد نظر ایجاد می کند، در غیر اینصورت  مرجعی (reference) به آنرا برگشت می دهد.

class CharacterFactory

    {

        private Hashtable characters = new Hashtable();

 

        public Character GetCharacter(char key)

        {

            Character character = characters[key] as Character;

            if (character == null)

            {

                switch (key)

                {

                    case 'A': character = new CharacterA(); break;

                    case 'B': character = new CharacterB(); break;

                    //...

                    case 'Z': character = new CharacterZ(); break;

                }

                characters.Add(key, character);

            }

            return character;

        }

    }