Design Patterns In Action Part-1: Implementing Observer Pattern for an Ecommerce Order Completion Workflow

Zuraiz Ahmed Shehzad
6 min readMar 9, 2023

--

Observer Pattern

Definition

The Observer pattern is a design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes. The purpose of the Observer pattern is to establish a one-to-many relationship between objects, so that when one object changes its state, all its dependents are notified and updated automatically.

Why we use Observer Pattern?

We use the Observer pattern when we want to decouple an object’s behavior from the objects it depends on. This promotes loose coupling between objects and makes it easier to modify and maintain the code in the future. By implementing the Observer pattern, we can create a flexible and extensible system that can respond to state changes in a consistent and predictable way. Some examples of where the Observer pattern is commonly used include user interface updates, event-driven systems, and asynchronous programming.

Lets implement Observer Pattern in a practical scenerio.

Our Scenario

Suppose you have an e-commerce platform and you want to send notifications to the customer and vendor when an order is completed. You also want to maintain a log of all order status changes and send an invoice to the customer when the order is completed.

To implement this functionality, you create an OrderStatus class that represents the status of an order. You also create a Logging class, an Email class, and an SmsNotification class that will handle the respective tasks of logging order status changes, sending an invoice to the customer's email address, and sending notifications to the customer and vendor's mobile numbers.

The OrderStatus class is observable, which means that the Logging, Email, and SmsNotification classes observe it. When the status of an order changes to "completed", the Logging class logs the order history, the Email class sends an invoice to the customer's email address, and the SmsNotification class sends notifications to the customer and vendor's mobile numbers.

When the Main method is executed, it creates instances of the OrderStatus, Logging, Email, and SmsNotification classes and attaches the observers to the OrderStatus instance. It then updates the status of the order to "completed". This triggers the observers to perform their respective tasks.

Implementation

IObserver Interface

The IObserver interface defines the Update method, which will be implemented by the observer classes.

public interface IObserver
{
void Update(string message);
}

Observable Class

The Observable class is an abstract class that defines the methods for attaching and detaching observers, as well as notifying the observers when the state of the object changes.

public abstract class Observable
{
private List<IObserver> observers = new List<IObserver>();

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

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

protected void Notify(string message)
{
foreach (var observer in observers)
{
observer.Update(message);
}
}
}

The observers list contains all the observers that are attached to the object. The Attach method adds an observer to the list, while the Detach method removes an observer from the list. The Notify method iterates over the observers in the list and calls the Update method on each observer, passing in the message parameter.

OrderStatus Class

The OrderStatus class extends the Observable class and represents the status of an order.

public class OrderStatus : Observable
{
private string status;

public string Status
{
get { return status; }
set
{
status = value;
Notify(status);

if (status == "completed")
{
NotifyCompleted();
}
}
}

private void NotifyCompleted()
{
Notify("Order completed");
}
}

The status field stores the current status of the order, and the Status property is used to get or set the status. When the status is set, the Notify method is called to notify the observers that the status has changed. If the status is "completed", the NotifyCompleted method is called, which in turn calls the Notify method with the string "Order completed".

Logging Class

The Logging class implements the IObserver interface and represents a logging system that logs order history.

public class Logging : IObserver
{
public void Update(string message)
{
// Do something with the message in the logging class
AppendOrderHistory(message);
}

private void AppendOrderHistory(string message)
{
// Append the message to the order history log
}
}

The Update method is called by the Observable object when the status of the order changes. The AppendOrderHistory method is called to append the message to the order history log.

Email Class

The Email class implements the IObserver interface and represents an email notification system that sends an invoice to the customer when an order is completed.

public class Email : IObserver
{
public void Update(string message)
{
// Do something with the message in the email class
if (message == "Order completed")
{
SendInvoiceToCustomer();
}
}

private void SendInvoiceToCustomer()
{
// Send the invoice to the customer's email address
}
}

The Update method is called by the Observable object when the status of the order changes. If the message is "Order completed", the SendInvoiceToCustomer method is called to send an invoice to the customer.

SmsNotification Class

The SmsNotification class implements the IObserver interface and represents an SMS notification system that sends notifications to the customer and vendor when an order is completed.

public class SmsNotification : IObserver
{
public void Update(string message)
{
// Do something with the message in the SMS notification class
if (message == "Order completed")
{
SendSMSNotificationToCustomer();
SendSMSNotificationToVendor();
}
}

private void SendSMSNotificationToCustomer()
{
// Send a notification to the customer's mobile number
}

private void SendSMSNotificationToVendor()
{
// Send a notification to the vendor's mobile number
}
}

The Update method is called by the Observable object when the status of the order changes. If the message is "Order completed", the SendSMSNotificationToCustomer and SendSMSNotificationToVendor methods are called to send notifications to the customer and vendor, respectively.

Main Method

The Main method creates instances of the OrderStatus, Logging, Email, and SmsNotification classes, attaches the observers to the OrderStatus instance, and updates the status of the order to "completed".

static void Main(string[] args)
{
var orderStatus = new OrderStatus();
var logging = new Logging();
var email = new Email();
var smsNotification = new SmsNotification();

orderStatus.Attach(logging);
orderStatus.Attach(email);
orderStatus.Attach(smsNotification);

// Update the status of the order to "completed"
orderStatus.Status = "completed";

Console.ReadLine();
}

This shows that the observers were notified when the status of the order changed to “completed”. The Logging class would append the message to the order history log, the Email class would send an invoice to the customer's email address, and the SmsNotification class would send notifications to the customer and vendor's mobile numbers.

Conclusion

In conclusion, the Observer pattern is a powerful design pattern that enables objects to communicate and respond to state changes in a flexible and decoupled manner. By decoupling objects through the use of observers and subjects, we can create systems that are more flexible, extensible, and easier to maintain. The Observer pattern is widely used in many programming contexts, including user interfaces, event-driven systems, and asynchronous programming.

--

--

Zuraiz Ahmed Shehzad

Software engineer with a passion for cloud computing and system design. Committed to creating user-friendly solutions. Let's innovate together.