Wykorzystanie wzorca Obserwator w aplikacji konsolowej

0

Witam wszystkich. Tworzę aplikację konsolową do zamawiania pizzy. Stworzyłem klasę Pizza: która ma właściwości: id,nazwa,cena,opis.Następnie stworzyłem klasę Admin: która ma List<Pizza>, metody dodające, usuwające i wyświetlające produkty. Chciałbym jeszcze dodać metodę do aktualizacji cen pizzy. W tym celu chciałem wykorzystać wzorzec "Obserwator" aby obiekty z listy mogły być obserwatorami. Stworzyłem klasę Observer która ma metodę dodającą i usuwająca obserwatorów (w parametrach metod przekazuje id produktu, a w ciele metody przypisuje lub usuwam zdarzenie aktualizacji cen). Ostatnia metoda powiadamia obserwatorów o wykonanych zdarzeniach.
Mam problem z prawidłowym działaniem obserwatora ponieważ, dodałem dwa produkty do obserwatora. I zaktualizowałem na tych produktach cenę a wartość produktów pozostała domyślna taka jak przed zmianą. Myślę, że źle zdefiniowałem metodę dodaj obserwatora, ponieważ tylko sprawdzam w liście czy id z listy zgadza się z parametrem metody a potem z tymi danymi nic więcej nie robię. Nie wiem jak dalej tych danych użyć. Może ktoś wie jak przerobić ten kod aby działało poprawnie? Z góry dziękuje za pomoc.

Klasa Admin:

 public class Admin: IObserver
    {
       public List<Pizza> listaProduktow = new List<Pizza>();
        public bool DodajProdukty(string name,string description,decimal price)
        {
            
            var item = listaProduktow.Count > 0 ? listaProduktow.Max(x => x.id) + 1 : 1;
            listaProduktow.Add(new Pizza {id= item, nazwaProduktu = name, opis = description, cena = price });
            return true;
        }

        public void UsunProdukt(int id)
        {
            var item = listaProduktow.FirstOrDefault(x => x.id == id);
            if(item!=null)
            {
                listaProduktow.Remove(item);
               
            }
        }
      
        public void WyswietlProdukty()
        {
            foreach (var item in listaProduktow)
            {
                Console.WriteLine("Id:"+item.id+" Nazwa pizzy " + item.nazwaProduktu+" opis: "+item.opis+" cena: "+ item.cena);
            }
        }
        public void AktualizujCene(decimal price)
        {
            foreach (var item in listaProduktow)
            {
                item.cena = price;
                Console.WriteLine("Cena {0} po zmianie {1}"+price,item.nazwaProduktu);
            }
        }
        public List<Pizza> PobierzListeProduktow()
        {
            return listaProduktow;
        }

Klasa Observer:

 public class Obserwer
    {
        public delegate void AktualizujStatus(decimal price);
        public event AktualizujStatus statusUpdate = null;
        Admin admin = new Admin();
      
        public void DodajObserwatora(int id )
        {
            List<Pizza> calledList = admin.PobierzListeProduktow();
            var item = calledList.FirstOrDefault(x => x.id == id);
        
            statusUpdate += new AktualizujStatus(admin.AktualizujCene);
            Console.WriteLine("Obiekt  jest obserwatorem");
           


        }
       
        public void UsunObserwatora(int id)
        {
            List<Pizza> calledList = admin.PobierzListeProduktow();
            var item = calledList.FirstOrDefault(x => x.id == id);
            statusUpdate -= new AktualizujStatus(admin.AktualizujCene);
            Console.WriteLine("Obiekt  nie jest obserwowany");
            
        }
        public void PowiadomObserwatorow(decimal price)
        {
            if (statusUpdate != null)
            {
                statusUpdate(price);
            }
        }
        public void ZmienCene(decimal price)
        {
            PowiadomObserwatorow(price);
        }
    }

Interfejs IObserver

 public  interface IObserver
    {
        void AktualizujCene(decimal price);
    }
2

Masz to teraz tak poplątane, że ciężko ogarnąć co chcesz osiągnąć. Coś takiego powinno pomóc:

public  interface IObserver
    {
        void priceChanged(int id, decimal newPrice);
    }

Klasa będąca właściwym obserwatorem:

public class ActualObserver: IObserver
    {
        @Override
         void priceChanged(int id, decimal newPrice) {
// tu sobie robisz co chcesz jak dostaniesz powiadomienie
    }

Klasa rozsyłająca powiadomienia:

public class Notifier
    {
        private List<IObserver> observers;
        public Notifier() {
                 observers = new ArrayList(); // czy cokolwiek
}

        public void notifyObservers(int id, decimal newPrice) {
                 foreach (var observer in observers) {
                             observer.priceChanged(id, newPrice);     
}
        public addObserver(IObserver observer) {
             observers.add(observer)
}
    }
3

A tak w ogóle, to obsługa zdarzeń C# to taki obserwator:

public void delegate PriceChangedDelegate(object sender, decimal oldPrice, decimal newPrice);

public class Pizza
{
    public event PriceChangedDelegate PriceChanged;

    public decimal Price
    {
        get { return price; }
        set 
        {
            decimal oldPrice = price;
            price = value;
            PriceChanged?.Invoke(this, oldPrice, price);
        }
    }
}

Pominąłem nieistotne rzeczy (jak pole price).
Potem, żeby się podłączyć do tego zdarzenia robisz po prostu:

pizza.PriceChanged += PizzaPriceChanged;

gdzie PizzaPriceChanged to metoda, która zostanie wywołana z tą samą sygnaturą, co delegat PriceChangedDelegate.
Możesz tak podłączyć i odłączać (-=) tylu obserwatorów, ilu chcesz.

A jeśli nie ogarniasz zapisu:

PriceChanged?.Invoke

To nic innego, jak:

if(PriceChanged != null)
  PriceChanged(this, oldPrice, price);

1 użytkowników online, w tym zalogowanych: 0, gości: 1