<-Back

Методичка з програмування: Singleton та Observer

Постановка задачі

У будинку є один холодильник, який може бути у трьох станах:

За станом холодильника стежать різні спостерігачі. Кожен має свої особливості поведінки:

Реакції спостерігачів

Спостерігач Empty ClosedWithFood OpenWithFood
Кіт (Cat) Йде читати книжку і відписується Спостерігає, але не підходить Хапає молоко і відписується
Собака (Dog) Ображається і відписується Гавкає, просить відкрити Радіє і їсть їжу, відписується
Вася (Vasya) Скаржиться мамі і відписується Знає, що є їжа, але не може дістати Зрадіє і бере бутерброди, відписується
Маша (Masha) Все одно на дієті, відписується Рада, що зачинено — не спокушається Бере шматочок салату і відписується

Реалізація на C#

using System;
using System.Collections.Generic;
using System.Linq;
// Інтерфейс спостерігача
public interface IObserver
{
    void Update(string state);
}

// Перелік станів холодильника
public enum FridgeState
{
    Empty,
    ClosedWithFood,
    OpenWithFood
}

// Клас Fridge (Singleton + Observable)
public class Fridge
{
    private static readonly Fridge instance = new Fridge();
    private List<IObserver> observers = new List<IObserver>();
    private FridgeState state;

    private Fridge() { state = FridgeState.Empty; }

    public static Fridge Instance
    {
        get { return instance; }
    }

    public void Attach(IObserver observer) { observers.Add(observer); }
    public void Detach(IObserver observer) { observers.Remove(observer); }

    public void ChangeState(FridgeState newState)
    {
        state = newState;
        Console.WriteLine($"\nХолодильник тепер: {state}");
        NotifyObservers();
    }

    private void NotifyObservers()
    {
        foreach (var observer in observers.ToList())
        {
            observer.Update(state.ToString());
        }
    }
}

// Реалізація спостерігачів

public class Cat : IObserver
{
    public void Update(string state)
    {
        if (state == FridgeState.Empty.ToString())
        {
            Console.WriteLine("Кіт: Ех... Порожньо. Я йду читати книжку.");
            Fridge.Instance.Detach(this);
        }
        else if (state == FridgeState.ClosedWithFood.ToString())
        {
            Console.WriteLine("Кіт: Мяу. Я спостерігаю, але не спішу...");
        }
        else if (state == FridgeState.OpenWithFood.ToString())
        {
            Console.WriteLine("Кіт: Мяу! Якщо там молочко — я перший!");
            Fridge.Instance.Detach(this);
        }
    }
}

public class Dog : IObserver
{
    public void Update(string state)
    {
        if (state == FridgeState.Empty.ToString())
        {
            Console.WriteLine("Собака: Гав! Порожньо?! Я ображений!");
            Fridge.Instance.Detach(this);
        }
        else if (state == FridgeState.ClosedWithFood.ToString())
        {
            Console.WriteLine("Собака: Гав! Відкрийте ж вже! Я голодний!");
        }
        else if (state == FridgeState.OpenWithFood.ToString())
        {
            Console.WriteLine("Собака: Ура! Гав-гав! Їжаааа!");
            Fridge.Instance.Detach(this);
        }
    }
}

public class Vasya : IObserver
{
    public void Update(string state)
    {
        if (state == FridgeState.Empty.ToString())
        {
            Console.WriteLine("Вася: Мамо, у нас холодильник порожній! :(");
            Fridge.Instance.Detach(this);
        }
        else if (state == FridgeState.ClosedWithFood.ToString())
        {
            Console.WriteLine("Вася: Я знаю, що там їжа... Але ж замкнули!");
        }
        else if (state == FridgeState.OpenWithFood.ToString())
        {
            Console.WriteLine("Вася: Ура! Нарешті бутерброди!");
            Fridge.Instance.Detach(this);
        }
    }
}

public class Masha : IObserver
{
    public void Update(string state)
    {
        if (state == FridgeState.Empty.ToString())
        {
            Console.WriteLine("Маша: Ну і добре, я все одно на дієті.");
            Fridge.Instance.Detach(this);
        }
        else if (state == FridgeState.ClosedWithFood.ToString())
        {
            Console.WriteLine("Маша: Добре, що зачинено — не спокушаюсь.");
        }
        else if (state == FridgeState.OpenWithFood.ToString())
        {
            Console.WriteLine("Маша: Ех... Лише шматочок салату, і більше нічого!");
            Fridge.Instance.Detach(this);
        }
    }
}

class Program
{
    static void Main()
    {
        Fridge fridge = Fridge.Instance;

        fridge.Attach(new Cat());
        fridge.Attach(new Dog());
        fridge.Attach(new Vasya());
        fridge.Attach(new Masha());

        fridge.ChangeState(FridgeState.ClosedWithFood);
        fridge.ChangeState(FridgeState.OpenWithFood);
        fridge.ChangeState(FridgeState.Empty);
		Console.WriteLine("\nТестування завершено.");
    }
}

Висновки