Observer – It lets the programs define a subscription mechanism to notify multiple objects, which means when the events happen, other objects can observe and immediately respond or modify object property.

From Design Pattern – Behavioral Patterns

Structure

Observer pattern – Class diagram UML

Applicability

  • Using its pattern when the programs change to the object state may require changing other objects, and the actual object sets are unknown beforehand or change dynamically.
  • Using its pattern when some objects must observe others in the program, but it is only for a limited time or in specific situations.

Pros and Cons

PROS

  • Open-closed principle – The developers can design the programs, which can introduce a new subscriber class without changing the publisher’s code and vice versa if there’s a publisher’s interface.
  • The programs can establish relations between objects at runtime.

CONS

  • Subscribers are notified in random order.
  • A large monolithic web application design architecture doesn’t scale well as new graphing or levied monolithic requirements.

How to Implement

#1 Basic Sample

static void Main(string[] args)
{
	var subject = new Subject();
	var ObserverA = new ConcreteObserver();
	subject.Attach(ObserverA);

	var ObserverB = new AnotherConcreteObserver();
	subject.Attach(ObserverB);

	subject.BusinessLogic();
	subject.BusinessLogic();
	
	subject.Detach(ObserverB);

	subject.BusinessLogic();

	Console.ReadKey();
}

public interface IObserver
{
	void Update(ISubject subject);
}

public interface ISubject
{
	void Attach(IObserver observer);
	void Detach(IObserver observer);
	void Notify();
}

public class Subject : ISubject
{
	public int State { get; set; } = -0;

	private List<IObserver> _observersList = new List<IObserver>();

	public void Attach(IObserver observer)
	{
		Console.WriteLine("Subject: Attached an object.");
		_observersList.Add(observer);
	}

	public void Detach(IObserver observer)
	{
		_observersList.Remove(observer);
		Console.WriteLine("Subject: Detached objects.");
	}

	public void Notify()
	{
		Console.WriteLine("Subject: Notifying observers.");

		foreach (var observer in _observersList)
			observer.Update(this);
	}

	public void BusinessLogic()
	{
		Console.WriteLine("\nSubject: Do something important.");
		State = new Random().Next(0, 10);

		Thread.Sleep(15);

		Console.WriteLine("Subject: My state has just changed to: " + State);
		Notify();
	}
}

public class ConcreteObserver : IObserver
{
	public void Update(ISubject subject)
	{
		if ((subject as Subject).State < 3)
			Console.WriteLine("Concrete Observer: Reacted to the event.");
	}
}

public class AnotherConcreteObserver : IObserver
{
	public void Update(ISubject subject)
	{
		if ((subject as Subject).State == 0 || (subject as Subject).State >= 2)
			Console.WriteLine("Another Concrete Observer: Reacted to the event.");
	}
}

#2 Web Application Project

Step 1 Create the interface and the service class files for the BLL. The interface class’ name sets “IObserverServices.” The service class’ name sets “ObserverServices.”

Fig 1 IObserverServices interface file source code.
Fig 2 ObserverServices class file source code.

Step 2 Create the observer interface class files, which name sets “IObserver.” Create the concrete observer class file, which name sets “ConcreteObserver.”

Fig 3 IObserver interface file source code.
Fig 4 ConcreteObserver class file source code.

Step 3 Create the subject interface class files. This class file’s name sets “ISubject.” Create the concrete subject class file which name sets “Subject.” In this sample, I create another class file that inherits the subject class file, which lets the concrete subject class object can a more extended application.

Fig 5 ISubject class file source code.
Fig 6 Subject class file source code.

Step 4 Create the observer-related files, such as the controller part files, the view part files, etc.

Step 5 Register the Core’ project observer-related files in the web project’ startup.cs files.

// Observer
services.AddScoped(typeof(IObserverServices), typeof(ObserverServices));
Fig 7 Observer result.

Reference

1 Comment

Leave a Reply