Хадгалагч (Memento)

Хадгалагч (Memento) хэв обьектын дотоод төлвийг түүний гадна гаргаж дараа нь хайрцаглалтын зарчмыг зөрчихгүйгээр обьектыг сэргээх боломжийг олгодог.

Хэвийг хаана ашиглах

  • Дараа нь сэргээх боломжтойгоор обьектын төлвийг хадгалах хэрэгтэй бол
  • Обьектын төлвийн хадгалалт хайрцаглалтын зарчмыг зөрчихгүйгээр хийгдэх хэрэгтэй бол

Энэхүү хэвийн түлхүүр ойлголт нь дотоод төлөв, хайрцаглалтын зарчим хоорондын балансыг сахин хадгалах юм. Хэрвээ бид хайрцаглалтыг зөрчихгүй бол обьектын төлвийг ердийн хувьсагчид хадгалах боломжтой шүү дээ. Харин эдгээр хувьсагчдад хандан утга олгох /setter/, утгыг авах /getter/ арга эсхүл шинжүүд үргэлж байгаад байдаггүй. Жишээ нь тоглоомд баатрыг удирддаг. Баатрын зэвсэг, амины хэмжээ, хүч гэх мэтээр бусад үзүүлэлтүүд тухайн баатрын обьект дотор агуулагддаг. Сүүлд өмнөх түвшиндээ буцан тоглоомыг шинээр эхлүүлэхийн тулд эдгээр бүх үзүүлэлтийг гадна хадгалах тохиолдол олонтаа гардаг. Энэ тохиолдолд хадгалагч хэв тусалж болно.
Хэвийн бүтцийн диаграмыг дараах байдлаар дүрсэлж болно.

patt_22_01

Хэвийн бүтцийг C# -аар харуулбал

class Memento
{
    public string State { get; private set;}
    public Memento(string state)
    {
        this.State = state;
    }
}
 
class Caretaker
{
    public Memento Memento { get; set; }
}
 
class Originator
{
    public string State { get; set; }
    public void SetMemento(Memento memento)
    {
        State = memento.State;
    }
    public Memento CreateMemento()
    {
        return new Memento(State);
    }
}

Оролцогчид

  • Memento - Originator обьектын төлвийн хадгалагч ба зөвхөн энэхүү Originator обьетод бүрэн хандалтыг олгоно.
  • Originator - өөрийн төлвийг хадгалах хадгалагч обьектыг үүсгэнэ.
  • Caretaker - зөвхөн Memento обьектыг хадгалах үүргийг гүйцэтгэх бөгөөд түүнд хадгалагчид хандах бүрэн эрх байхгүй. Өөрөөр хэлбэл класс хадгалах үйлдлээс өөр юуг ч хийж чадахгүй.

Одоо бодит жишээ авч үзье. Бидэнд тоглоомын баатрын төлвийг хадгалах хэрэг гарлаа гэе.

    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;
            Hero hero = new Hero();
            hero.Shoot(); // Буудлага хийлээ, 9 сум үлдсэн
            GameHistory game = new GameHistory();

            game.History.Push(hero.SaveState()); // тоглоомыг хадгалах

            hero.Shoot(); // Буудлага хийлээ, 8 сум үлдсэн

            hero.RestoreState(game.History.Pop());

            hero.Shoot(); // Буудлага хийлээ, 8 сум үлдсэн

            Console.Read();
        }
    }

    // Originator
    class Hero
    {
        private int patrons = 10; // сумны тоо
        private int lives = 5; // амины тоо

        public void Shoot()
        {
            if (patrons > 0)
            {
                patrons--;
                Console.WriteLine("Буудлаа. {0} сум үлдсэн", patrons);
            }
            else
                Console.WriteLine("Сум дууссан");
        }
        // төлвийн хадгалалт
        public HeroMemento SaveState()
        {
            Console.WriteLine("Тоглоомыг хадгалах. Параметрүүд: {0} сум, {1} амь", patrons, lives);
            return new HeroMemento(patrons, lives);
        }

        // төлвийн сэргээлт
        public void RestoreState(HeroMemento memento)
        {
            this.patrons = memento.Patrons;
            this.lives = memento.Lives;
            Console.WriteLine("Тоглоомыг сэргээх. Параметрүүд: {0} сум, {1} амь", patrons, lives);
        }
    }
    // Memento
    class HeroMemento
    {
        public int Patrons { get; private set; }
        public int Lives { get; private set; }

        public HeroMemento(int patrons, int lives)
        {
            this.Patrons = patrons;
            this.Lives = lives;
        }
    }

    // Caretaker
    class GameHistory
    {
        public Stack<HeroMemento> History { get; private set; }
        public GameHistory()
        {
            History = new Stack<HeroMemento>();
        }
    }

Програмыг ажлуулбал

patt_22_02

үр дүн гарна. Энд Originator -ийн үүргийг төлөв нь сум, амины тоогоор тодорхойлогдох Hero класс гүйцэтгэнэ. HeroMemento класс тоглоомын баатрын төлвийг хадгалахад зориулагдсан. Hero обьект өөрийн төлвийг SaveState() аргаар HeroMemento -д хадгалаад RestoreState() аргаар сэргээнэ. GameHistory класс төлвийг хадгалахад зориулагдсан бөгөөд бүх төлвүүдийг стекд хадгалах тул сүүлийн төлвийг амархан гарган ирэх боломжтой.
Memento хэв дараах давуу талтай.

  • Системийн холбоог багасгана
  • Мэдээллийг хайрцаглан хадгална
  • Төлвийг хадгалах, сэргээхэд энгийн интерфейсийг тодорхойлно

Хэрвээ их хэмжээний мэдээллийг хадгалах хэрэгтэй болбол бүх төлвийг хадгалахад зардал /хугацаа, санах ой/ ихсэх тул нөөцийн дутагдалтай тулгарч мэднэ.

Мэдээлэл таалагдсан бол найзуудтайгаа хуваалцаарай.

  Нээгдсэн тоо: 2404 Төлбөртэй

Exception бол програмчлалын олон хэлэнд байдаг алдааг боловсруулах стандарт механизм. Хичээлээр С# дээр алдааны боловсруулалтыг хэрхэн үүсгэн хэрэгжүүлэхийг авч үзнэ. Та дэлгэц дээрээсээ харж байгаа код бол хийж болохгүй аргачлалын тод жишээ байгаа.

  Нээгдсэн тоо: 2163 Төлбөртэй

Гурван суурь I хичээлд бид C# хэлний Тодорхой бус /далд/ төрөлжилт, Нэргүй төрлүүдийн талаар үзсэн. Энэ удаад Өргөжүүлэлтийн аргуудын талаар авч үзнэ. Ямарч програмын хэлийг сайн эзэмшихийн тулд тухайн хэлний нарийн механизмуудыг ойлгосон байх хэрэгтэй. Түүнээс давталт, нөхцөлт операторууд гэх мэтийн бүх хэлэнд байдаг цөөн тооны ерөнхий ойлголтоор програмын кодыг бичнэ гэвэл бараг бүтэхгүй зүйл. Бичсэн байсан ч таны код эхлэн суралцагч эсхүл сонирхогчийн түвшинд л харагдахын дээр тавигдсан асуудлыг бүрэн шийднэ гэхэд хэцүү.

  Нээгдсэн тоо: 534 Бүртгүүлэх

Програмчлалын C# хэлэнд өгөгдлийн энгийн төрлүүдээс гадна enum буюу дурдах /тоолох/ гэсэн төрөл бий. enum төрөл логик холбоотой тогтмолуудаар илэрхийлэгдэнэ.

Төрлийг enum оператороор зарладаг.

enum нэр
{
    // тоологын утгууд
    утга1,
    утга2,
    .......
    утгаN
}

enum араас тооллогын нэрийг өгнө. Дараа нь хаалтанд таслалаар тусгаарлан тооллогын утгууддыг тогтмолуудыг бичнэ.

  Нээгдсэн тоо: 1158 Төлбөртэй

Өгөгдлийн сантай ажиллах явцад түүнд төрөл бүрийн хүсэлтүүд өгөн өгөгдөл боловсруулах шаардлага тогтмол гардаг. Энэ хичээлд өгөгдлийн сангийн хүсэлтийг үүсгэх талаар авч үзэх болно. Өгөгдлийн сангийн хүсэлтүүд маш олон төрлүүд байдаг болохоор бүгдийг авч үзэх боломжгүй. Гэхдээ ерөнхий аргачлалыг ойлгосон байхад та ямарч хүсэлтийг үүсгэн ашиглах боломжтой.

Үйл явдал /event/ тодорхой үйлдэл хийгдсэн талаар системд мэдэгддэг. Хэрвээ бид энэхүү үйлдлийг ажиглах хэрэгтэй бол яг энд…

Нээгдсэн тоо : 337

 

Манай төсөл олон хуудсуудтай болон тэдгээрийн хооронд динамикаар шилжилт хийж байгаа ч тухайн үед шилжилт хийгдсэн хуудаст тохирох…

Нээгдсэн тоо : 428

 

Зочин (Visitor) паттерн классуудыг өөрчлөхгүйгээр тэдгээрийн обьектуудын үйлдлийг тодорхойлох боломжийг олгоно. Зочин хэвийг ашиглахдаа классуудын хоёр ангилалыг тодорхойлно.…

Нээгдсэн тоо : 393

 

Лямбда-илэрхийлэл нь нэргүй аргын хураангуй бичилтийг илэрхийлнэ. Лямбда-илэрхийлэл утга буцаадаг, буцаасан утгыг өөр аргын…

Нээгдсэн тоо : 474

 

Кодийн сайжруулалт /рефакторинг/ хичээлээр програмийн кодоо react -ийн зарчимд нийцүүлэн компонентод салгасан.…

Нээгдсэн тоо : 550

 

Хадгалагч (Memento) хэв обьектын дотоод төлвийг түүний гадна гаргаж дараа нь хайрцаглалтын зарчмыг зөрчихгүйгээр обьектыг сэргээх боломжийг олгодог.

Нээгдсэн тоо : 538

 

Делегаттай нэргүй арга нягт холбоотой. Нэргүй аргуудыг делегатийн хувийг үүсгэхэд ашигладаг.
Нэргүй аргуудын тодорхойлолт delegate түлхүүр үгээр…

Нээгдсэн тоо : 659

 

Математикт харилцан урвуу тоонууд гэж бий. Ямар нэгэн тооны урвуу тоог олохдоо тухайн тоог сөрөг нэг зэрэг дэвшүүлээд…

Нээгдсэн тоо : 775

 

Төсөлд react-router-dom санг оруулан чиглүүлэгчдийг бүртгүүлэн тохируулсан Санг суулган тохируулах хичээлээр бид хуудас…

Нээгдсэн тоо : 792

 
Энэ долоо хоногт

Нээгдсэн тоо : 1613

 

[-252; 299) завсарт орших 18 -д үлдэгдэлгүй хуваагдах тоонуудын нийлбэрийг ол.

Нээгдсэн тоо : 1045

 

тэгшитгэлийг бод.

Нээгдсэн тоо : 268