Implementing the Null Object Pattern in C#

In software development, the Null Object Pattern is a design pattern that provides a default or "null" implementation of an interface or class. It is particularly useful in scenarios where we want to avoid null checks and gracefully handle cases where an object may be null. In this article, we'll explore how to implement the Null Object Pattern using an example scenario from a shopping cart application in C#.

Understanding the Problem

Consider a shopping cart application where users can add items to their cart and calculate the total price of all items. However, some items may not have a price available, such as items that are out of stock or have not been priced yet. In such cases, we want to avoid null checks and handle the absence of price gracefully.

Designing the Solution

To solve this problem, we'll utilize the Null Object Pattern. We'll create an abstract class called Price that represents the price of an item in the cart. This class will define a method called GetAmount(), which returns the price of the item as a decimal.

Next, we'll create two concrete implementations of the Price class: RegularPrice and NoPrice. The RegularPrice class will represent an item with a known price, while the NoPrice class will represent an item with an unknown or unavailable price.

The RegularPrice class will implement the GetAmount() method to return the actual price of the item. The NoPrice class, on the other hand, will implement GetAmount() to return a default or placeholder price, such as zero.

By using the Null Object Pattern, we can ensure that we always have a valid Price object for each item, even if the price is not available. This eliminates the need for null checks and simplifies the logic when calculating the total price.

Implementing the Solution

Let's dive into the implementation of the solution in C#.

First, we define the Price abstract class:

No alt text provided for this image

The Price class provides a single method, GetAmount(), which will be implemented differently in the RegularPrice and NoPrice classes.

Next, we implement the RegularPrice and NoPrice classes that derive from the Price class:

No alt text provided for this image


The RegularPrice class represents an item with a known price and stores the price amount in a private field. The GetAmount() method in this class returns the actual price.

The NoPrice class represents an item with an unknown or unavailable price. In this case, the GetAmount() method returns a default or placeholder price, which is zero.

Now, let's update our ShoppingCartItem class to include a Price property:

No alt text provided for this image

The ShoppingCartItem class now has a ItemPrice property of type Price, which represents the price of the item.

Next, let's update our ShoppingCart class to calculate the total price and average price of all items, ignoring items with NoPrice:

No alt text provided for this image

The CalculateTotalPrice() method calculates the total price of all items in the cart by summing up the amounts obtained from the GetAmount() method of each item's Price object.

The CalculateAveragePrice() method calculates the average price of the items, ignoring items with NoPrice. It keeps track of the count of valid items and the total price of those items. It then divides the total price by the count to get the average.

By checking if the item's Price object is not an instance of NoPrice, we can exclude items with NoPrice from the average price calculation.

Conclusion

In this article, we explored how to implement the Null Object Pattern in C# using an example scenario from a shopping cart application. By utilizing the Null Object Pattern, we can avoid null checks and gracefully handle cases where objects may be null or have unavailable values. This pattern simplifies the logic and improves the overall maintainability of the code.

We implemented the Null Object Pattern by creating an abstract Price class and two concrete implementations: RegularPrice and NoPrice. We then updated the ShoppingCart class to utilize the Price objects for calculating the total and average prices, while ignoring items with NoPrice.

By using the Null Object Pattern, we achieved a cleaner and more robust design for our shopping cart application, making it easier to handle scenarios where item prices are unknown or unavailable.

To view or add a comment, sign in

More articles by Mohsen Mohammadi

Explore content categories