الگوی 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;

        }

    }

 

تسلیت

پدر امیر یک معلم بود، هست و خواهد ماند. یک معلم به همه دنیا تعلق دارد، به تمام بشریت. معلم روح جاری خداوند روی زمین است، خداوند بشر را خلق می کند و روح را در آن می دمد، معلم روح را می سازد و آن را به سمت بالا پرواز می دهد، …

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

او رفت و رسید، اما همیشه خاطره او در قلب ما و همه شاگردانش خواهد ماند.

« خانه دوست کجاست؟» در فلق بود که پرسید سوار.

آسمان مکثی کرد.

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

و به انگشت نشان داد سپیداری و گفت:

«نرسیده به درخت،

گوچه باغی است که از خواب خدا سبز تر است.

و در آن عشق به اندازه پرهای صداقت آبی است.

می روی تا ته آن کوچه که از پشت بلوغ، سر بدر می آرد،

پس به سمت گل تنهایی می پیچی،

دو قدم مانده به گل،

پای فواره جاوید اساطیر زمین می مانی

و ترا ترسی شفاف فرا می گیرد.

در صمیمیت سیال فضا، خش خشی می شنوی:

کودکی می بینی

رفته از کاج بلندی بالا، جوجه بردارد از لانه نور

و از او می پرسی

خانه دوست کجاست.»

و هزاران حرف دیگر که می خواهیم بنویسم، اما نمی توانم.

الگوی Memento

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

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

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

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

نمودار UML، این الگو بصورت زیر است:

همانطوریکه در بالا اشاره شد، ما نیاز داریم تا حالت یک شی را ذخیره و بازیابی کنیم، این شی با نام originator در این الگو مشخص می شود. اما نحوه ذخیره کردن وضعیت شی موجود به این صورت است که زمانیکه برنامه Client درخواست ذ   خیره کردن را از شی originator می کند. این شی (originator)، تمام صفاتی را که برای بازیابی حالتش نیاز است را، در یک شی دیگر به نام Memento قرار می دهد و آن را به Client ازسال میکند (در نمودار مقدار صفت state از شی originator، در مقدار صفت stateشی Memento قرار می گیرد.). ما نیاز داریم تا اشیاء از نوع Memento را، نگهداری و مدیریت کنیم. برای اینکار از کلاسی به نام caretaker، استفاده می کنیم. زمانیکه یک شی Mementoایجاد می شود، آن شی به مجموعه اشیاء Caretaker اضافه می شود. وقتی که یک عمل undo انجام می شود شی Caretaker با یک شی دیگر (client)، همکاری می کند تا یک شی Memento انتخاب شود. بعد از انتخاب شی Memento ، آن شی متد setMemento شی Originator را فراخوانی می کند تا حالت انتخاب شده را بازیابی کند.

فرضی کنید شما در حال طراحی یک برنامه ویرایشگر متن هستید، و یکی از نیازهای مطرح شده توسط کاربران این مورد است که وقتی آنها قسمتی از یک متن را کپی می کنند، آن قسمت به یک لیست اضافه شود و نمایش داده شود. سپس زمانیکه کاربر به یکی از متن های کپی شده نیاز داشت، یکی از آنها از لیست انتخاب کند تا متن انتخاب شده به متن اصلی اضافه شود(عمل paste). دقیقا چیز شبیه clipboard برنامه Microsoft Office Word.

می خواهیم این خواسته را توسط الگوی Memento، طراحی کنیم. در این مثال شی که ما نیاز داریم، حالتش را ذخیره کنیم و سپس در صورت نیاز بازیابی کنیم، شی Clipboard است.

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

Public Class originator

Private _Clipboard As String

Public Property Clipboard() As String

Get

Return _Clipboard

End Get

Set(ByVal value As String)

_Clipboard = value

End Set

End Property

Public Function createMemento() As memento

Return New memento(_Clipboard)

End Function

Public Sub setMemento(ByVal _memento As memento)

_Clipboard = _memento.Clipboard

End Sub

End Class

کلاس memento که برای ذخیره اطلاعات مورد نیاز برای یازیابی حالت یک نمونه از شی originator به کار می رود.

Public Class memento

Private _Clipboard As String

Public Sub New(ByVal Data As String)

_Clipboard = Data

End Sub

Public Property Clipboard() As String

Get

Return _Clipboard

End Get

Set(ByVal value As String)

_Clipboard = value

End Set

End Property

End Class

کلاس caretaker برای نگهداری نمونه های مختلفی از کلاس memento به کار می رود. در ا ینجا برای نگهداری این نمونه ها از ArrayList استفاد شده است. تو سط متد list، مجموعه اشیایی memento برای نمایش به کاربر برگشت داده می شود. تا کاربر یکی از آنها را در صورت نیاز انتخاب کند.

Public Class caretaker

Private memento As New ArrayList

Public Sub Add(ByVal _memento As memento)

memento.Add(_memento)

End Sub

Public Function List() As ArrayList

Return memento

End Function

End Class

برای تست کلاس های بالا از یک فرم به نام FrmTest استفاده شده است. که یک کنترل ListBox بر روی آن قرار دارد تا مقادیر موجود در هر کدام از نمونه های شی memento را نمایش دهد. تا کاربر بتواند حالت مورد نیاز خود را از میان آنها انتخاب کند.

Public Class FrmTest

Dim Ins As New originator

Dim List As New caretaker

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Ins.Clipboard = “Ali”

List.Add(Ins.createMemento())

Ins.Clipboard = “asd”

List.Add(Ins.createMemento())

Ins.Clipboard = “sdf”

List.Add(Ins.createMemento())

Me.ListBox1.DataSource = List.List

Me.ListBox1.DisplayMember = “Clipboard”

End Sub

Private Sub ListBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.Click

Ins.setMemento(List.List(Me.ListBox1.SelectedIndex))

End Sub

End Class

توجه:  در پیاده سازی مثال بالا، بعضی از قوانین شی گرایی نادیده گرفته شده است.(تصحیح به عهده دوستان)

رسیدن

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

نامه های عاشقانه یک پیامبر

جبران خلیل جبران

ما می توانیم، چو نکه ما می توانیم.

 

Observer Pattern

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

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

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

در هر دو مسئله بالا، ما یک شی داریم که مجموعه ای از اشیاء به آن وابسته هستند. هر زمانی که وضعیت شی مورد نظر تغییر می کند، اشیاء دیگر از آن تغییر آگاه می شوند. در این الگو، مجموعه اشیاء وابسته را Observer   های می نامیم و شی را که دیگر اشیاء به آن وابسته هستند را Subject می نامیم. برای نمونه در مثال اول، افرادی که در سایت عضو می شوند یک شی Observer   هستند. و شی خبر، همان  Subject  هست.

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

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

1-       Subject باید یک اینترفیس برای ثبت (registering) و انصراف از عضویت (unregistering) و اطلاع از تغییرات را آماده کند.

2-       Subject باید اطلاعات حالتی را که، observer ها برای آن ریجستر شده اند را به observer  ها ارسال کند.

3-       Observer  باید یک اینترفیس برای دریافت پیام از Subject آماده کند.

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

 

 

با یک مثال دیگر کار را ادامه می دهیم. فرض کنید که در اداره شما ، در داده های پایگاه داده مرکزی تغییرات غیر مجازی، داده شده است. برای حل این مشکل مدیران پیشنهاد کرده اند که هر تغییری که در پایگاه داده می شود، باید توسط یک پیام، به افراد مشخص شده ای اعلام شود. شما برای حل این مشکل، الگوی Observer  را در نظر می گیرید. دقیقا بر طبق نمودار عمل می کنیم و با یک حالت فرض این مثال را پیاده سازی می کنیم.

 

اینترفیس مربوط به subject

Public Interface subject

    Sub Attach(ByVal Ins As Observer)

    Sub Detach(ByVal Ins As Observer)

    Sub Notify()

End Interface

اینترفیس مربوط به Observer  

Public Interface Observer

    Sub Update(ByVal operation As String, ByVal record As String)

End Interface

کلاس database که اینترفیس مربوط به subject را پیاده سازی می کند.

Public Class dataBase

    Implements subject

    Private observers As ArrayList

    Private operation As String

    Private record As String

 

    Public Sub New()

        observers = New ArrayList

    End Sub

 

    Public Sub Attach(ByVal Ins As Observer) Implements subject.Attach

        observers.Add(Ins)

    End Sub

 

    Public Sub Detach(ByVal Ins As Observer) Implements subject.Detach

        observers.Remove(observers)

    End Sub

 

    Private Sub Notify() Implements subject.Notify

        For I As Integer = 0 To observers.Count – 1

            Dim Ins As Observer = observers(i)

            Ins.Update(operation, record)

        Next

    End Sub

    Public Sub editDatabase(ByVal ope As String, ByVal rec As String)

        Me.operation = ope

        Me.record = rec

        Notify()

    End Sub

 

End Class

کلاس Archiver که اینترفیس Observer   را پیاده سازی می کند.

Public Class Archiver

    Implements Observer

    Public Sub Update(ByVal operation As String, ByVal record As String) Implements Observer.Update

        MessageBox.Show(“The archiver says a “ + operation + ” operation was performed on “ + record)

    End Sub

End Class

کلاس boss که اینترفیس Observer   را پیاده سازی می کند.

Public Class Boss

    Implements Observer

    Public Sub Update(ByVal operation As String, ByVal record As String) Implements Observer.Update

        MessageBox.Show(“The boss says a “ + operation + ” operation was performed on “ + record)

    End Sub

End Class

 

کلاس client که اینترفیس Observer   را پیاده سازی می کند.

Public Class client

    Implements Observer

    Public Sub Update(ByVal operation As String, ByVal record As String) Implements Observer.Update

        MessageBox.Show(“The client says a “ + operation + ” operation was performed on “ + record)

    End Sub

End Class

 

تست

Dim DB As New dataBase

Dim Ar As New Archiver

Dim Bo As New Boss

Dim Cl As New client

DB.Attach(Ar)

DB.Attach(Bo)

DB.Attach(Cl)

DB.editDatabase(“Delete”, “Record 1”)

در مثال بالا، ما سه نوع Observer   داریم. که هر وقت تغییری در پایگاه داده اعمال می شود، با یک پیام به آنها اعلام می شود.

کار

ژان همین که مرد، وارد مکان بسیار زیبایی شد. چیز هایی دید که خواب شان را هم ندیده بود. مردی با لباس سفید نزدیک شد:

«هر چه بخواهید در اختیارتان است: غذا، لذت، سرگرمی.»

ژان هر کاری را که در دوران زندگی اش دلش می خواست، انجام داد. بعد از سالهای لذت بخش بسیار، سراغ مرد سفید پوش رفت:

«هر چه را که می خواستم، بدست آوردم. حالا دلم می خواهد کار کنم تا مثمر ثمرتر باشم.»

مرد سفید پوش گفت: «بسیار متاسفم. اما این از دست من بر نمی آید، این جا کار نداریم.»

ژان با آزردگی گفت: «چه وحشتناک! باید تمام ابدیت را به کسالت بگذازنم! ترجیح می دهم به جهنم بروم!»

مرد سفید پوش نزدیگ شد و آرام گفت: «پس فکر می کنید کجایید؟»

الگوها

یکی دیگر از نکات مثبت دیگر در الگوهای طراحی این است که آنها ماحصل تجربه‏اند و نه مباحث آکادمیک. به عبارت دیگر برای خلق یک الگو، لازم نیست شما در آزمایشگاههای مهندسی نرم‏افزار به دنبال کشف نمونه‏ای جدیدی از آن باشید، بلکه باید در حین تجربه و انجام کار، حواستان به گذشته‏تان باشد یا به آینده؛ و طرح این سئوال که آیا من درگذشته این مسئله را حل کرده‏ام؟ آیا مسئله‏ای که با آن روبرو هستم دیگر بار ممکن است تکرار شود؟( الگوهای طراحی، محاسن و معایب (Design Patterns Pros & Cons) )

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

ما در دنیایی از الگوهای زندگی می کنیم. از همان روزهای اول زندگی، الگوها را فرا می گیریم و بکار می بریم. ما از همان دوران کودکی، چیز هایی را که در اطرفم تکرار می شنوند می بینیم و آنها را تکرار می کنیم. حتی بطور غریزی در شرایط مشابه، عکس العمل های مشابهی از خود نشان می دهیم. پس مفهوم الگو، از اولین روزهای زندگی با ما بوده است و  با ما خواهد بود. اینها را نوشتم تا بگویم وقتی درباره الگوها صحبت می کنیم، درباره مفهوم جدیدی صحبت نمی کنیم. بحث اصلی من این است، که برای استفاده از الگوها در نرم افزار(در تمام چرخه حیات یک نرم افزار)، آیا فقط تجربه های که در این رشته دارم را می توانیم بصورت الگوهای در بیاوریم و ار آن استفاده کنیم. یا می توانیم از تمام تجربیاتی که در زندگی روزمره داریم یا حتی تجربیاتی که افراد دیگر در رشته های مختلف دارند استفاده کنیم و با تغییر در شیوه بیان، آنها را در فرمتی ارائه دهیم که بشود در چرخه تولید نرم افزار یا هر مسئله دیگری از آن استفاده کنیم. برای نمونه، یکی از قوانین شیمی که در کتاب دوره دبیرستان که حتما آنرا خواندید، به اینصورت بود: اگر بر یک تعادل پویا تغییری تحمیل شود، آن تعادل در جهتی جا به جا می شود، که تغییر تحمیل شده را تعدیل کند و یا آنرا به کمترین مقدار ممکن برساند. این فانون را من چند سال قبل، در کتاب شیمی حواندم، ولی آن را به عنوان الگوی در شرایط مشابه، برای خودم قرار دادم. و به اعتقادم این قانون می تواند در هر سازمانی و هر تیمی بکار گرفته شود. یا یک مثال دیگر، همه افرادیکه مثل خودم حتی آشنایی بسیار کمی با RUP، داشته باشند. حتما این اصل اساسی RUP، را شنیده اند، اگر به مشکلات حمله نکنید، آنها به شما حمله خواهند کرد. دوباره جمله بسیار زیبایی است، که حتما باید بکار گرفته شود. اما می گویند شرکت رشنال برای استخراج این اصول و سایر خروجیهای RUP، هزاران پروژه را مورد ارزیابی قرار دادند. ولی به نظر من بعضی از این اصول مثل اصل بالا، از زمانهای دور وجود داشته ولی چون بطور شفاهی بیان شده است و یا به دلایلی دیگر، مورد توجه قرار نگرفته است. در پایین داستانی را از کتاب قصه هایی یرای پدران، فرزندان، نوه ها، می آورم که به قول گردآورنده این مجموعه، آقای پائولو کوئلیو، حتی منشا و خالق این داستان ها نیز معلوم نیست، که دقیقا همان اصل، RUP را بیان می کند اما به شیوه ای جذابتر(توصیه می کنم حتما بخوانید و مقایسه کنید):

استاد بزرگ و نگهبان، مراقبت از یک صومعه ذن را بین خود تقسیم کردند. یک روز، تکهبان در گذشت  و باید کس دیگری را جایگزین او می کردند.

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

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

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

استاد گفت: مساله این است.

شاگردها، حیران، به گلدان نگاه کردند: به طرح های پیچیده و نادر روی سفال، به تازگی و زیبایی گل. منظور چه بود؟ چه کار باید می کردند؟ معما چه بود؟

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

استاد گفت: تو نگهبان جدید مایی.

وقتی شاگرد به جای خودش برگشت، استاد بزرگ توضیح داد:

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

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

تولد

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

من یک سال بزرگتر شدم.

الگوی استراتژی (Strategy Pattern)

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

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

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

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

الگوی استراتژی گزینه مناسبی برای مسائلی است که می توانند از چندین الگوریتم مختلف به مقصود خود برسند.

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

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

1

Shell Sort

2

Quick Sort

3

Merge Sort

ما برای مرتب سازی در این برنامه دارای سه استراتژی هستیم. که هر کدام را به عنوان یک کلاس جداگانه در نظر می گیریم (همان کلاس های ConcreteStrategy). برای اینکه کلاس Client  بتواند به سادگی یک از استراتژی ها را انتخاب کنید بهتر است که تمام کلاس های استراتزی دارای اینترفیس مشترک باشند. برای این کار می توانیم یک کلاس abstract تعریف کنیم و ویژگیهای مشترک کلاس های استراتژی را در آن قرار دهیم و کلاس های استراتژی آنها را به ارث ببرند(همان کلاس Strategy) و پیاده سازی کنند.

کلاس abstract که کلاس های استراتژی آنرا به ارث می برند.

abstract class SortStrategy

    {

        public abstract void Sort(ArrayList list);

    }

 

کلاس مربوط به QuickSort

class QuickSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

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

        }

    }

 

کلاس مربوط به ShellSort

    class ShellSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

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

        }

    }

 

کلاس مربوط به MergeSort

    class MergeSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

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

        }

    }

 

کلاس Context که یکی از استراتزیها را برای مرتب کردن لیست به کار می برد.

    class SortedList

    {

        private ArrayList list = new ArrayList();

        private SortStrategy sortstrategy;

 

        public void SetSortStrategy(SortStrategy sortstrategy)

        {

            this.sortstrategy = sortstrategy;

        }

 

        public void Add(string name)

        {

            list.Add(name);

        }

 

        public void Sort()

        {

            sortstrategy.Sort(list);

        }

    }

 

  

الگو

از شخص پرسیدند:

بهترین الگو برای پیروی چیست؟ افراد پرهیزگاری که زندگی شان را وقف خدا می کنند و نمی پرسند چرا؟ یا افراد با فرهنگی که می کوشند باری تعالی را بفهمند.

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

گفتند: کودک هیچ نمی داند. هنوز نمی داند واقعیت چیست؟

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