مطالب
پیاده سازی الگوی طراحی Memento

Memento یک الگوی طراحی مفید و ساده است که برای ذخیره و بازیابی state یک object استفاده می‌شود. در بعضی از مقالات از آن به عنوان snapshot نیز یاد شده است! اگر با git  کار کرده باشید، این مفهوم را می‌توان در git بسیار یافت؛ هر commit به عنوان یک snapshot میباشد که میتوان به صورت مکرر آن را undo کرد و یا مثال خیلی ساده‌تر میتوان به ctrl+z در سیستم عامل اشاره کرد.

به مثال زیر توجه کنید:

Int temp;
Int a=1;
temp=a;
a=2;
.
.
a=temp;

شما قطعا در برنامه نویسی با کد بالا زیاد برخورد داشته‌اید و آن‌را به صورت مکرر انجام داده‌اید. کد بالا را در قالب یک object بیان میکنیم. به مثال زیر توجه کنید:

int main()
{
  MyClass One = new MyClass();
  MyClass Temp = new MyClass();
  // Set an initial value.
  One.Value = 10;
  One.Name = "Ten";
  // Save the state of the value.
  Temp.Value = One.Value;
  Temp.Name = One.Name;
  // Change the value.
  One.Value = 99;
  One.Name = "Ninety Nine";
  // Undo and restore the state.
  One.Value = Temp.Value;
  One.Name = Temp.Name;
}

در کد بالا با استفاده از یک temp، شیء مورد نظر را ذخیره کرده و در آخر مجدد داده‌ها را درون شیء، restore  میکنیم.


 از مشکلات کد بالا میتوان گفت :

۱- برای هر object باید یک شیء temp ایجاد کنیم.

۲- ممکن است بخواهیم که حالات یک object را بر روی هارد ذخیره کنیم. با روش فوق کدها خیلی پیچیده‌تر خواهند شد.

۳- نوشتن کد به این سبک برای پروژه‌های بزرگ، پیچیده و مدیریت آن سخت‌تر می‌شود.


پیاده سازی memento

ما این مثال را در قالب یک پروژه NET Core  onsole. ایجاد میکنیم. برای این کار یک پوشه‌ی جدید را ایجاد و درون ترمینال دستور زیر را وارد کنید:

dotnet new console

روش‌های زیادی برای پیاده سازی memento وجود دارند. برای پیاده سازی memento ابتدا یک abstract class را به شکل زیر ایجاد میکنیم: 

abstract class MementoBase
{
  protected Guid mementoKey = Guid.NewGuid();
  abstract public void SaveMemento(Memento memento);
  abstract public void RestoreMemento(Memento memento);
}

اگر به کلاس بالا دقت کنید، این کلاس قرار است parent کلاس‌های دیگری باشد که داری دو متد SaveMemento و RestoreMemento برای ذخیره و بازیابی و همچنین یک Guid برای نگهداری state‌های مختلف میباشد.

ورودی متدها از نوع memento میباشد. پس کلاس memento را به شکل زیر ایجاد می‌کنیم:

class Memento
{
    private Dictionary<Guid, object> stateList = new Dictionary<Guid, object>();
    public object GetState(Guid key)
    {
        return stateList[key];
    }
    public void SetState(Guid key, object newState)
    {
        stateList[key] = newState;
    }
    public Memento()
    {
    }
}

در کد بالا با یک Dictionary می‌توان هر object را با کلیدش ذخیره کنیم. توجه کنید که value دیکشنری از نوع object میباشد و چون object پدر تمام object‌های دیگر است پس می‌توانیم هر نوع داده‌ای را در آن ذخیره کنیم. تا اینجا، Memento پیاده سازی شده است. میتوان این کار را با جنریک‌ها نیز پیاده سازی کرد.

در ادامه می‌خواهیم یک کلاس بسازیم و حالت‌های مختلف را در آن بررسی کنیم. کلاس زیر را ایجاد کنید:

class ConcreteOriginator : MementoBase
{
  private int value = 0;
  public ConcreteOriginator(int newValue)
  {
    SetData(newValue);
  }
  public void SetData(int newValue)
  {
    value = newValue;
  }
  public void Speak()
  {
    Console.WriteLine("My value is " + value.ToString());
  }
  public override void SaveMemento(Memento memento)
  {
    memento.SetState(mementoKey, value);
  }
  public override void RestoreMemento(Memento memento)
  {
    int restoredValue = (int)memento.GetState(mementoKey);
    SetData(restoredValue);
  }
}

کلاس ConcreteOriginator از کلاس MementoBase ارث بری کرده و دو متد RestoreMemento و SaveMemento را پیاده سازی میکند و همچنین دارای یک مشخصه value می‌باشد. برای خروجی گرفتن، متد main را به صورت زیر پیاده سازی می‌کنیم:

static void Main(string[] args)
{
  Memento memento = new Memento();
  // Create an originator, which will hold our state data.
  ConcreteOriginator myOriginator = new ConcreteOriginator("Hello World!", StateType.ONE);
  ConcreteOriginator anotherOriginator = new ConcreteOriginator("Hola!", StateType.ONE);
  ConcreteOriginator2 thirdOriginator = new ConcreteOriginator2(7);
  // Set some state data.
  myOriginator.Speak();
  anotherOriginator.Speak();
  thirdOriginator.Speak();
  // Save the states into our memento.
  myOriginator.SaveMemento(memento);
  anotherOriginator.SaveMemento(memento);
  thirdOriginator.SaveMemento(memento);
  // Now change our originators' states.
  myOriginator.SetData("Goodbye!", StateType.TWO);
  anotherOriginator.SetData("Adios!", StateType.TWO);
  thirdOriginator.SetData(99);
  myOriginator.Speak();
  anotherOriginator.Speak();
  thirdOriginator.Speak();
  // Restore our originator's state.
  myOriginator.RestoreMemento(memento);
  anotherOriginator.RestoreMemento(memento);
  thirdOriginator.RestoreMemento(memento);
  myOriginator.Speak();
  anotherOriginator.Speak();
  thirdOriginator.Speak();
  Console.ReadKey();
}
تا خط ۱۲، مراحل عادی کد نویسی را پیش رفته‌ایم. در خطوط ۱۳ تا ۱۵، داده را در Memento ذخیره میکنیم. در خطوط ۱۷ تا ۱۹، داده‌های اشیاء را با استفاده از متد SetData عوض میکنیم. در خطوط ۲۰ تا ۲۲ با متد Speak، مقدار value را نمایش میدهیم و در خطوط ۲۴ تا ۲۶، داده‌ها را Restore میکنیم و در آخر دوباره مقدار value را نمایش میدهیم.
برنامه را اجرا کنید .خروجی به شکل زیر خواهد بود:
Hello World! I'm in state ONE
Hola! I'm in state ONE
My value is 7
Goodbye! I'm in state TWO
Adios! I'm in state TWO
My value is 99
Hello World! I'm in state ONE
Hola! I'm in state ONE
My value is 7
اشتراک‌ها
پاسخ به برترین سوالات Python
Wondering how the pros solve that Python question? Find out with Content Developer Eric Camplin, as he hosts a team of Python Developers, including popular expert Steve Dower, who answer top Python questions for all skill levels and dive into best practices for this versatile and easy-to-use programming language.

Get practical tips, learn EAFP (“It’s Easier to Ask Forgiveness than Permission”) in working with files in Python, call external commands, look at “lazy lists,” use True/False properties of Python lists to check whether one is empty, and lots more. Plus, over time, watch this space for additional question and answer sets, as you explore the top questions programmers have about Python. 
پاسخ به برترین سوالات Python
اشتراک‌ها
Rust 1.69.0 منتشر شد

The Rust team is happy to announce a nice version of Rust, 1.69.0. Rust is a programming language empowering everyone to build reliable and efficient software. 

Rust 1.69.0 منتشر شد
اشتراک‌ها
اعتبارسنجی JSON با JSON-Schema

When you’re dealing with complex and structured data, you need to determine whether the data is valid or not. JSON-Schema is the standard of JSON documents that describes the structure and the requirements of your JSON data. In this two-part series, you’ll learn how to use JSON-Schema to validate data. 

اعتبارسنجی JSON با JSON-Schema
اشتراک‌ها
کتاب Akka.NET مختصر و مفید

Akka.NET is an open-source actor model framework written exclusively for Microsoft.NET in C# and compatible with .NET Core. It simplifies the building of scalable, concurrent, high-throughput, and low-latency systems, making life for software developers a bit easier. Zoran Maksimovic's Akka.NET Succinctly will show readers what an actor model is and how to work with actors in Akka.NET, taking them from an actor's lifecycle through to unit testing.


کتاب Akka.NET مختصر و مفید