using System.Collections.Generic;
public static void Main()
var product = new Product
product.Attach(new ProductPriceObserver());
product.Attach(new ProductStockObserver());
product.UpdatePrice(999M);
public record ProductObserverArgs
public int Id { get; set; }
public int? PreviousStock { get; init; }
public int? NewStock { get; init; }
public decimal? PreviousPrice { get; init; }
public decimal? NewPrice { get; init; }
public interface IProductObserver
void Update(ProductObserverArgs args);
public class ProductStockObserver : IProductObserver
public void Update(ProductObserverArgs args)
if (args.PreviousPrice.GetValueOrDefault() > 0 || args.NewStock == 0) return;
Console.WriteLine($"The product is in stock. Stock : {args.NewStock}");
public class ProductPriceObserver : IProductObserver
public void Update(ProductObserverArgs args)
if (args.NewPrice.GetValueOrDefault() >= args.PreviousPrice.GetValueOrDefault()) return;
Console.WriteLine($"The product price dropped. {args.PreviousPrice} -> {args.NewPrice}");
public class ObservableProduct
private List<IProductObserver> Observers { get; set; } = new();
public void Attach(IProductObserver observer)
public void Detach(IProductObserver observer)
Observers.Remove(observer);
protected void Notify(ProductObserverArgs args)
foreach (var observer in Observers)
public class Product : ObservableProduct
public int Id { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
public void UpdateStock(int stock)
var previousStock = Stock;
Notify(new ProductObserverArgs
PreviousStock = previousStock,
public void UpdatePrice(decimal price)
var previousPrice = Price;
Notify(new ProductObserverArgs
PreviousPrice = previousPrice,