Шаблони дизайну - Швидкий посібник щодо шаблону спостерігача.

Шаблон спостерігача - це дуже часто використовуваний візерунок. Насправді це так часто, що стандартизується у багатьох мовах / бібліотеках програмування. У Java він існує injava.util.Observer (застаріло в Java 9). У Python він так само близький, як apip встановлює шаблон-спостерігач. У C ++ ми можемо іноді використовувати прискорену бібліотеку, точніше #include . Однак він широко використовується в промисловості як рішення на замовлення. Щоб вміти правильно використовувати його і зрозуміти його складність, нам потрібно зануритися і дослідити його.

Шаблон спостерігачів класифікується серед моделей поведінкового дизайну. Шаблони поведінкового дизайну найбільш конкретно стосуються спілкування між класами / об'єктами. [за шаблонами дизайну пояснено просто]

Що таке модель спостерігачів? Крім ходового монітора, який транслює аналогове телебачення (як на малюнку). Мета цього шаблону - визначити взаємозв'язок "один на багато" таким чином, що коли один об'єкт змінює стан, інші повідомляються та оновлюються автоматично. Точніше, бажає бути поінформованим про події, що відбуваються в системі. Давайте складемо шматочки головоломки разом у три етапи.

Крок 1 - Ключові слова

Визначення ключових слів - секретний рецепт у цій серії швидких посібників. Цей метод допоміг мені по-справжньому зрозуміти шаблони дизайну, важко кодувати їх на увазі і зрозуміти відмінності між іншими моделями дизайну.

  1. Тема: Він вважається зберігачем інформації, даних або ділової логіки.
  2. Зареєструватись / долучити: спостерігачі реєструються на тему, оскільки хочуть отримувати сповіщення про зміни.
  3. Подія: події виступають запускаючими тему, щоб повідомити всіх спостерігачів.
  4. Повідомте: Залежно від реалізації, суб'єкт може "підштовхувати" інформацію до спостерігачів, або спостерігачі можуть "тягнути", якщо їм потрібна інформація від суб'єкта.
  5. Оновлення: спостерігачі оновлюють свій стан незалежно від інших спостерігачів, однак їх стан може змінюватися залежно від викликаної події.

Крок 2 - Діаграма

Давайте розділимо цей дизайн на різні класи, щоб трохи спростити це.

  • ConcreteObservers - це класи, які містять інформацію, специфічну для поточного екземпляра. Функція оновлення викликається операцією notify () суб'єкта. Спостерігачі оновлюються незалежно залежно від їх поточного стану.
  • Спостерігач - це батьківський клас конкретних спостерігачів. Він містить предметний екземпляр. Коли спостерігач ініціалізується, він реєструється / приєднується до об'єкта.
  • Клас "Тема" має список або колекцію спостерігачів. Коли спрацьовує подія, вона викликає операцію notify (), яка перебирає всіх спостерігачів, викликаючи їх функцію оновлення.

Крок 3 - Код за прикладом

Я б запропонував скопіювати клас коду за класом з мого сховища git “Andreas Poyias” або фрагментів нижче (у наданому порядку) та вставити його в будь-який із доступних онлайн-редакторів C ++, як c ++ shell, jdoodle, onlineGDB та запустити це для спостереження за результатами. Потім прочитайте коментарі чи опис нижче. Не витрачайте час, ретельно читаючи його (це означає одну хвилину, не менше і не більше).

Приклад: Розгляньте футбольну гру. Багато прихильників спостерігають за грою. Ми розділили прихильників на дві категорії за віком, молодих та старих. Коли їхня команда забиває гол, вболівальники реагують по-різному залежно від віку та рівня хвилювання.
Тепер поговоримо з термінами, які використовуються для моделі спостерігачів:

  • Гра є темою, а прихильники - спостерігачі.
  • Усі спостерігачі приєднані / зареєстровані на предмет, і вони отримують сповіщення, коли забиває їх футбольна команда (тригер-подія, якщо їхня команда забиває).
  • Спостерігачі оновлюють свою поведінку залежно від отриманого повідомлення.

Тема
Для цього класу нам потрібен доступ до списку спостерігачів. Коли спостерігачі збираються зареєструватися, вони викликають функцію theattach (це), щоб додати себе до наявного списку (це екземпляр спостерігача). Коли подія запускається, сповіщайте () всіх спостерігачів про незалежне оновлення свого стану. У цьому прикладі курок - якщо футбольна команда спостерігача забила.

#include 
#include 
використання простору імен std;
Тема класу {
    вектор  спостерігачі;
    bool забив; // тригер, подія
загальнодоступний:
    // реєструвати спостерігачів
    недійсне вкладення (спостерігач * obs) {
        observers.push_back (obs);
    }
   
   // Це ПОДІЇ
   // Встановіть if набрав та повідомте ВСІХ спостерігачів
   пустота setScored (bool Score) {
      забитий = оцінка;
      сповістити ();
   }
bool getScored () {
      повернутий забитий;
   }
   // реалізація сповіщень далі знижується
   // так, що сценарій збирається і запускається
   недійсне повідомлення ();
};

Спостерігач
Цей клас залежить від предмета, в якому він зареєстрований. Коли конкретні спостерігачі ініціалізуються, вони приєднуються до об'єкта. У цьому прикладі стан кожного спостерігача - це його хвилювання, що проходить у грі.

клас спостерігач
{
    Тема * subj;
    int хвилюванняLevel; // держава
  загальнодоступний:
    Спостерігач (Subject * mod, int excLevel)
    {
        subj = mod;
        excitementLevel = excLevel;
        // Спостерігачі реєструються / приєднуються до Теми
        subj-> прикріплювати (це);
    }
    віртуальне оновлення void () = 0;
  захищено:
    Тема * getSubject () {
       повернути subj;
    }
    void setExcitementLevel (int excLevel) {
       excitementLevel = excLevel;
    }
    int getExcitementLevel () {
       повернення хвилюванняLevel;
    }
};

Це декларація предмета :: notify (), і як ми вже згадували, його завдання - сповістити всіх спостерігачів про оновлення свого стану.

недійсна тема: notify () {
  for (int i = 0; i  update ();
}

Конкретні спостерігачі
Конкретні спостерігачі успадковуються від класу Observer, і всі вони повинні мати функцію оновлення. У цьому прикладі конкретні спостерігачі розрізняють молодих та старих прихильників. Якщо рівень їх хвилювання стає занадто високим, старші прихильники ризикують інфарктами, а молодші - ризиком випити та поїсти. Їх стан оновлюється незалежно, як ми докажемо в основній функції далі нижче.

клас Old_ConcreteObserver: громадський спостерігач
{
   загальнодоступний:
     // Викликає батьківський конструктор для реєстрації з предметом
     Old_ConcreteObserver (Тема * mod, int div)
        : Спостерігач (mod, div) {}
     // Для людей похилого віку, якщо рівень хвилювання
     // понад 150 вони ризикують інфарктом
     недійсне оновлення ()
     {
        bool набрав = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        якщо (забив && getExcitementLevel ()> 150)
        {
          cout << "Команда Старого Спостерігача забила !!"
               << "Рівень його хвилювання"
               << getExcitementLevel ()
               << "стежте за інфарктами!" << endl;
        } else {
          cout << "Команда не забила. Yeeeih не про що хвилюватися"
               << endl;
        }
    } // завершити оновлення ()
};
клас Young_ConcreteObserver: громадський спостерігач
{
   загальнодоступний:
     // Викликає батьківський конструктор для реєстрації з предметом
     Young_ConcreteObserver (Тема * mod, int div)
       : Спостерігач (mod, div) {}
     // Для людей похилого віку, якщо рівень хвилювання
     // понад 100 вони ризикують інфарктом
     недійсне оновлення ()
     {
        bool набрав = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        якщо (забив && getExcitementLevel ()> 100)
        {
          cout << "Команда юного спостерігача забила !!"
               << "Рівень його хвилювання"
               << getExcitementLevel ()
               << "не пити і не їздити !!" << endl;
        } else {
          cout << "Команда не забила. Вам нічого не турбуватися"
               << endl;
       }
    } // завершити оновлення ()
};

Основна функція
Конкретні спостерігачі реєструються в екземплярі предмета. Їх стан - рівень збудження, який є другим параметром. Коли подія спрацьовує "subj.setScored (true)", тоді закликаєтьсяSubject :: notify () для оновлення зареєстрованих спостерігачів. У нижченаведеному сценарії у нас є три спостерігачі, молодий Obs1 надмірно схвильований і ризикує пити та їхати, старий Obs1 також перезбуджений, інакший ризик (серцевий напад). Нарешті, молодому Obs2, який також молодий, як перший, нема про що турбуватися, оскільки він не перезбуджений.

Важливо зауважити, що три спостерігачі оновлювались незалежно від їх стану (рівня хвилювання) та типу (молодих чи старих).
int main () {
   Тема subj;
   Young_ConcreteObserver youngObs1 (& subj, 100);
   Old_ConcreteObserver oldObs1 (& subj, 150);
   Young_ConcreteObserver youngObs2 (& subj, 52);
   subj.setScored (вірно);
}
// Вихід
// Команда юного спостерігача забила !! Рівень його хвилювання - 101
// не пити і не їздити !!
// Команда Старого Спостерігача забила !! Його рівень хвилювання - 151 годинник
// поза серцевими нападами! Команда не забила.
// Йех, про що не турбуватися

Існує кілька переваг для використання шаблону Observer та кілька моментів, які слід зазначити, коли до цього шаблону слід звернутись [Навчання шаблонів дизайну Python].

  • Шаблон Observer надає конструкцію, де Суб'єкт і спостерігач слабко з'єднані. Предмет не повинен знати про клас ConcreteObserver. Будь-який новий спостерігач може бути доданий в будь-який момент часу. Не потрібно змінювати Subject, коли додається новий спостерігач. Спостерігачі та суб'єкти не пов'язані між собою та не є незалежними один від одного, тому зміни в Темі чи спостерігачі не вплинуть один на одного.
  • Немає можливості для композиції, оскільки інтерфейс Observer може бути екземпляром.
  • Якщо спостерігач неправильно застосовується, він може легко додати складності та призвести до проблем з продуктивністю.
  • Повідомлення можуть бути недостовірними і можуть спричинити за собою змагальні умови або невідповідність.

Наступний блог стане коротким посібником щодо схеми дизайну містків. Це структурна модель дизайну, яка досить широко використовується в галузі. Не забудьте сподобатися / заплескати мій пост у блозі та слідкуйте за моїм обліковим записом. Це дає мені задоволення, що я допоміг деяким колегам-розробникам і змусив мене продовжувати писати. Якщо є конкретна модель дизайну, про яку ви хотіли б дізнатися, то повідомте мене, щоб я могла надавати її вам у майбутньому.

Інші швидкі посібники щодо моделей дизайну:

  1. Шаблони дизайну - Швидкий посібник по абстрактній фабриці.
  2. Шаблони дизайну - Швидкий посібник щодо мостового шаблону.
  3. Шаблони дизайну - Швидкий посібник щодо шаблону для будівельників.
  4. Шаблони дизайну - Швидкий посібник з візерунком декораторів.
  5. Шаблони дизайну - Швидкий посібник з фасадної схеми.
  6. Шаблони дизайну - Швидкий посібник із шаблону спостерігачів.
  7. Шаблони дизайну - Швидкий посібник по Singleton Pattern.