Observer mode of C# design mode

Observer pattern


This blog will introduce the Observer pattern, which is used to describe the dependencies between objects and provide a solution for the linkage of multiple objects. It is a very frequently used design pattern.

Pattern Classification

Behavioral Design Patterns.

The reason for the pattern

In a software system, objects do not exist in isolation, and a change in the behavior of an object may cause changes in the behavior of one or more other related objects. There will be a linkage between them, the so-called pulling one hair will move the whole body. In order to better describe the one-to-many or one-to-one relationship between objects, the observer pattern came into being. It defines a one-to-many dependency relationship between objects, so that an object change can affect other objects.

Sources of Pattern Inspiration

In daily life, traffic lights direct the increasingly congested urban traffic. When the red light is on, the passing cars will stop; when the green light is on, the cars can continue to move forward. In this process, the traffic light is the observation target of the car, and the car is the observer of the traffic light. With the change in traffic lights, the behavior of cars has also changed, and a single traffic light can direct multiple cars.

Pattern Class Diagram

insert image description here

The Observer pattern usually contains the following four objects:

Subject (observation target):

The observation target is the object to be observed. An observer set is defined in the target. When the observation target changes, the method corresponding to each observer in the set will be called.

ConcreteSubject (specific observation target):

The specific observation target usually contains data that changes frequently. When its state changes, it will send notifications to its observers, and at the same time it will implement the abstract method in the abstract observation target.

Observer (observer):

The observer will react to the change of the observed target, and the observer is generally defined as an interface, which declares the method of updating the data.

ConcreteObserver (concrete observer):

A reference to the specific target object is maintained in the specific observer. Usually, when implementing, it will add itself to its observer collection through the method of observing the target. That is, the addition of observers in the observation target is done by the observers themselves.

Code

Example: When the price of the stock purchased by the stock buyer changes, the system will automatically send a notification to all shareholders who purchased the stock. Try designing the system using the observer pattern.

Observation target: trading system

using System.Collections.Generic;

namespace Observer.Observer.Question6
{
    
    
    public class TradingSystem
    {
    
    
        private static TradingSystem _instance;

        public static TradingSystem GetInstance
        {
    
    
            get
            {
    
    
                if (_instance == null)
                {
    
    
                    _instance = new TradingSystem();
                }

                return _instance;
            }
        }

        private readonly Dictionary<string, List<Buyer>> _buyerList = 
            new Dictionary<string, List<Buyer>>();

        public void Add(string stockName, Buyer buyer)
        {
    
    
            if (_buyerList.ContainsKey(stockName))
            {
    
    
                if (_buyerList[stockName] != null)
                {
    
    
                    _buyerList[stockName].Add(buyer);
                }
                else
                {
    
    
                    _buyerList[stockName] = new List<Buyer>();
                    _buyerList[stockName].Add(buyer);
                }
            }
            else
            {
    
    
                _buyerList.Add(stockName, new List<Buyer>());
                _buyerList[stockName].Add(buyer);
            }
        }

        public void Remove(string stockName, Buyer buyer)
        {
    
    
            
        }

        public void Notify(Message message)
        {
    
    
            foreach (var buyer in _buyerList[message.StockName])
            {
    
    
                buyer.GetMessage(message);
            }
        }
    }
}

Observer class

namespace Observer.Observer.Question6
{
    
    
    public abstract class Buyer
    {
    
    
        public string Name {
    
     get; set; }

        public Buyer(string name)
        {
    
    
            Name = name;
        }
        public abstract void GetMessage(Message message);
    }
}

Stock information category:

namespace Observer.Observer.Question6
{
    
    
    public class Message
    {
    
    
        public int Money;
        public string StockName;
    }
}

Stock class:

using Observer.Observer.Example;

namespace Observer.Observer.Question6
{
    
    
    public abstract class Stock
    {
    
    
        private int _money;
        public int Money
        {
    
    
            get => _money;
            set
            {
    
    
                _money = value;
                OnMoneyChange();
            }
        }
        public string Name {
    
     get; set; }

        public Stock(int money, string name)
        {
    
    
            Name = name;
            _money = money;
            
        }

        private void OnMoneyChange()
        {
    
    
            Message message = new Message();
            message.Money = Money;
            message.StockName = Name;
            TradingSystem.GetInstance.Notify(message);
        }
    }
}

Program class:

using Observer.Observer.Example;
using Observer.Observer.Question6;

namespace Observer
{
    
    
    internal class Program
    {
    
    
        public static void Main()
        {
    
    
            XiaoHong xiaoHong = new XiaoHong("xiaohong");
            XiaoMing xiaoMing = new XiaoMing("xiaoming");
            Stock beijingStock = new BeiJingStock(100,"beijing");
            Stock shanghaiStock = new ShangHaiStock(200, "shanghai");
            TradingSystem.GetInstance.Add(beijingStock.Name, xiaoHong);
            TradingSystem.GetInstance.Add(beijingStock.Name, xiaoMing);
            beijingStock.Money = 200;
        }
    }
}

Observer pattern summary

Advantages of the observer pattern:

  1. The observer mode can realize the separation of the presentation layer and the data logic layer, and defines a stable message update transmission mechanism.
  2. Observer mode supports broadcast communication, and the observation target will send notifications to all registered observer objects, simplifying the difficulty of one-to-many system design.

Disadvantages of observer pattern:

  1. If an observation target object has many direct and indirect observers, it takes time to notify all observers.
  2. There may be a circular dependency between the observer and the observed object. Once triggered, the system may crash.

Guess you like

Origin blog.csdn.net/BraveRunTo/article/details/118993574