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

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

  1. حوایجی
    ۸ خرداد ۱۳۸۶ در ۱۷:۱۳ | #1

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

  1. بدون بازتاب