بایگانی

بایگانی آذر

الگوی Iterator

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

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

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

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

دیاگرام الگوی Iterator

تعریف اینترفیس IIterator

Public Interface IIterator

 Function FirstItem() As Object

 Function NextItem() As Object

 Function IsDone() As Boolean

 Function CurrentItem() As Object

End Interface

 

پیاده سازی اینترفیس IIterator

Public Class ConcreteIterator

 Implements IIterator

 Private List As New ArrayList

 Private Current As Integer = 0

 

 Public Sub New(ByVal VarList As ArrayList)

 List = VarList

 End Sub

 

 Public Function CurrentItem() As Object Implements IIterator.CurrentItem

 Return List(Current)

 End Function

 

 Public Function FirstItem() As Object Implements IIterator.FirstItem

 Current = 0

 If IsDone() Then

 Return List(Current)

 Else

 Return Nothing

 End If

 End Function

 

 Public Function IsDone() As Boolean Implements IIterator.IsDone

 If Current >= List.Count Then

 Return False

 Else

 Return True

 End If

 End Function

 

 Public Function NextItem() As Object Implements IIterator.NextItem

 Current += 1

 If IsDone() Then

 Return List(Current)

 Else

 Return Nothing

 End If

 End Function

End Class

 

تعریف اینترفیس Aggregate

Public Interface IAggregate

 Function CreateIterator() As IIterator

End Interface

 

پیاده سازی اینترفیس Aggregate و کلاس Book

Public Class Book

 Implements IAggregate

 Private _Name As String

 Private _Chapters As New ArrayList

 

 Public Property Name() As String

 Get

 Return _Name

 End Get

 Set(ByVal value As String)

 _Name = value

 End Set

 End Property

 

 Public Sub New()

 

 End Sub

 

 Public Sub New(ByVal VarName As String)

 _Name = VarName

 End Sub

 

 Public Sub Add(ByVal Chapter As Chapter)

 _Chapters.Add(Chapter)

 End Sub

 

 Public Function CreateIterator() As IIterator Implements IAggregate.CreateIterator

 Return New ConcreteIterator(_Chapters)

 End Function

End Class

 

 

تعریف کلاس Chapter

Public Class Chapter

 Private _Name As String

 Public Property Name() As String

 Get

 Return _Name

 End Get

 Set(ByVal value As String)

 _Name = value

 End Set

 End Property

 Public Sub New()

 

 End Sub

 Public Sub New(ByVal VarName As String)

 _Name = VarName

 End Sub

End Class

 

نحوه استفاده

Dim Book As New Book(“Book1″)

Book.Add(New Chapter(“Chapter 1″))

Book.Add(New Chapter(“Chapter 2″))

 

Dim Iterator As IIterator = Book.CreateIterator

Dim Ins As Chapter = Iterator.FirstItem

While Iterator.IsDone

 System.Console.WriteLine(Ins.Name)

 Ins = Iterator.NextItem

End While

 

 

الگوی Composite

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

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

با این طراحی  Clinet می تواند یک مجموعه از اشیاء FileSystemComponent را ایجاد کند. و با استفاده از متد addComponent، شی  DirComponent، نمونه های مختلفی از FileSystemComponents را به DirComponent اضافه کند.

هنگامیکه Clinet بخواهد سایز هر کدام از این اشیاء را استخراج کند، به سادگی متد getComponentSize را فراخوانی کند، Client نباید از نحوه محاسبه و عملیاتی که برای اندازه گیری سایز یک مولفه صورت می گیرد آگاه باشد. در این مورد، client با هر دو شی FileComponent و DirComponent به یک صورت رفتار می کند.

Clinet  در مورد متد مشترک getComponentSize، با هر دو شی  FileComponent و DirComponent رفتار یکسانی را دارد. اما Clinet   برای فراخوانی متدهای مانند addComponent و getComponent نیاز دارد که دو شی را از همدیگر تشخیص دهد، چونکه این متدها فقط برای DirComponent تعریف شده است. به همین دلیل client نیاز دارد تا نوع شی مورد نظر را برای فراخوانی این متدها چک کند تا مطمئن شود که با یک نمونه از DirComponent سر و کار دارد.  برای بهبود این طراحی بگونه ای که نیازی به تشخیص تفاوت بین دو شی وجود نداشته باشد، طراحی را به چه صورت تغییر می دهد.

ما می خواهیم طراحی را بگونه ای تغییر دهیم که clinet  نیازی به تشخیص شی مرکب DirComponent از FileComponent نداشته باشد، و با هر دو شی به یک صورت رفتار کند.

طراحی را می توانیم به این صورت تغییر دهیم که، متدهای addComponent و getComponent را به اینترفیس مشترک FileSystemComponent  انتقال دهیم، و یک پیاده سازی پیش فرض برای این متدها انجام دهیم و اینترفیس مشترک FileSystemComponent   را به یک کلاس abstract تغییر دهیم. پیاده سازی پیش فرض برای این متدها بخاطر FileComponent  هست و کار خاصی را انجام نمی دهد. اما کلاس DirComponent این متدها را بازنویسی مجدد می کند تا پیاده سازی خاص خود را انجام دهد.

با این کار مشکل قبلی ما حل می شود، چون کلاس پدر FileSystemComponent، دارای یک پیاده سازی پیش فرض برای متدهای addComponent و getComponent هست، و دیگر clinet   نیاز به کنترل نوع شی برای فراخوانی این دو متد ندارد.

تصور کنید که می خواهیم یک متد جدید با نام  removeComponent را به کلاس DirComponent اضافه کنیم، در اینصورت این متد را به پدر FileComponent نیز اضافه می کنیم و یک پیاده سازی پیش فرض برای این متد در نظر می گیریم.

با طراحی بالا ما توانستیم مشکل خود را حل کنیم، اما روشی که برای غلبه بر مسئله استفاده کردیم، الگوی Composite نام دارد. ما در مواقعی از این الگو استفاده می کتیم که یک شی پیچیده داریم و می خواهیم آنرا به یک سلسله مراتب از اشیاء کل و جز (part-whole hierarchy) تجزیه کنیم. یا همانند مثال بالا،  client قادر باشد تفاوت بین اشیاء مرکب (DirComponent) و اشیاء منفرد را نادیده بگیرید. و client با همه اشیاء موجود در ساختار مرکب بصورت یکسان رفتار کند.

کلاس دیاگرام این الگو به صورت زیر است:

در دیاگرام بالا کلاس Leaf، کلاس های هستند که دارای فرزند نیستند مانند کلاس FileComponent در مثال.

کلاس Composite، کلاسی مانند DirComponent در مثال می باشد. در این کلاس رفتارهای مربوط به مولفه های که دارای فرزند هستند تعریف می گردد.

کلاس FileSystemComponent همان کلاسFileSystemComponent با ویژگیهای که در بالا اشاره شد هست.

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

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

 

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

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

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

 

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

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

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

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

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

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

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

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

 

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

 

 

نام الگو

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

هدف (intent)

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

نام مستعار

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

ساختار

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

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

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

همکاریها (Collaborations)

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

نتایج‌ (Consequences)

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

پیاده سازی

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

نمونه کد

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

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

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

 

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

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

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

۳-      الگوهای رفتاری(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

 

فهرست الگوهای طراحی