-
Notifications
You must be signed in to change notification settings - Fork 0
Null Object Pattern : Design Patterns
The null object pattern is a very simple and useful pattern. When implemented properly, it can greatly reduce the amount of code by eliminating all the checks and guards against null object references. The pattern is used to shield clients from having to handle a null case when a service or an objects returns a null. This is accomplished by returning an object that is a ‘null implementation’ for the case when no result is found.
The Null Object pattern is also know as the ‘Stub’, the ‘Active Null’ pattern, or the ‘Do Nothing’ pattern.
Instead of passing null references and checking for the presence of null before any operation, you create a specific class that represents a non-functional dependency. This class implements an expected interface or inherits from an abstract class but includes no functionality. Its methods and properties perform no action and return default, fixed values. This allows any dependant object to use null object dependencies without performing any pre-checks, simplifying the code.
The null object pattern is usually used with other design patterns.
- The null object class itself is often created as a Singleton. This limits the number of instances to one, which is ideal as null objects generally have no state and no functionality so creating additional objects would add unnecessary overhead to your software.
- Another design pattern that is often found with the null object pattern is the strategy pattern. When one of the strategies requires no functionality, a null object can be used.
- A third common associated pattern is the factory method pattern, where the factory may return a null object instance.
BEFORE
public interface IShape
{
void Draw();
}
public class Square : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a Square...");
}
}
public class ShapeService
{
public IShape GetShapeById(int id)
{
// Details of method removed for simplicity
var square = GetShapeFromDatabase(id);
return square;
}
}
public class Program
{
public static void Main()
{
var shapeService = new ShapeService();
var shape = shapeService.GetShapeById(3);
shape.Draw(); // Can cause a null reference exception
}
}
//With Exception Handling
public class Program
{
public static void Main()
{
var shapeService = new ShapeService();
var shape = shapeService.GetShapeById(3);
if (shape != null)
{
shape.Draw();
}
}
}
AFTER
public interface IShape
{
void Draw();
}
public class Square : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a Square...");
}
}
public class NullShape : IShape
{
public void Draw()
{
// Do Nothing
}
}
public class ShapeService
{
public IShape GetShapeById(int id)
{
var square = GetShapeFromDatabase(id);
return square ?? new NullShape();
}
}
public class Program
{
public static void Main()
{
var shapeService = new ShapeService();
var shape = shapeService.GetShapeById(3);
shape.Draw(); // No need to check for null
}
}
https://github.com/anandtpatel/CSharpCode/blob/master/src/CSharpCode/DesignPatterns/NullObject.cs