Take, for example, the following class.
Listing 1
public class ReviewStatus
{
private string _code = string.Empty;
private string _name = string.Empty;
#region " Properties "
public string Code
{
get
{
return _code;
}
set
{
_name = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
#endregion
#region " Constructors "
protected ReviewStatus(string code, string name)
{
_code = code;
_name = name;
}
#endregion
public static ReviewStatus Accepted()
{
return new ReviewStatus("A", "Accepted");
}
public static ReviewStatus Cancelled()
{
return new ReviewStatus("C", "Cancelled");
}
public static ReviewStatus Processed()
{
return new ReviewStatus("P", "Processed");
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is ReviewStatus))
return false;
ReviewStatus status = (ReviewStatus)obj;
return this.Code.Equals(status.Code);
}
}
This class represents the status of a review in a business
system. It can be Accepted, Cancelled, or Processed, and has two properties
that contain the codified and named values. The review status, though, could
have no status to report, especially if a new business object was created and
not in the review phase. To handle this through a Null object we can use the
following object.
Listing 2
public class NullReviewStatus: ReviewStatus
{
#region " Constructors "
private NullReviewStatus(): base(string.Empty, string.Empty){}
#endregion
public static ReviewStatus Empty()
{
return new NullReviewStatus();
}
}
Because the constructor on ReviewStatus is declared
protected, the NullReviewStatus class can inherit from ReviewStatus to expose a
new static method: Empty(). Empty returns the equivalent of an empty status,
meaning no status is assigned by assigning string.Empty values to the code and
name parameters. To note, string.Empty is returned so it does not cause null
reference checks when using the properties, like using the Code.Equals() method
in the ReviewStatus code sample.
To make null checking easier, Fowler recommends adding an
IsNull method, which the ReviewStatus class returns a static value of false.
NullReviewStatus overrides the IsNull method and returns a value of true,
noting that the object is null. This makes it easier to process whether or not
the object is actually null.
Listing 3
//ReviewStatus Implementation
public virtual bool IsNull()
{
return false;
}
//NullReviewStatus Implementation
public override bool IsNull()
{
return true;
}
An object that uses the ReviewStatus object can default the
private variable of a business class to Empty.
Listing 4
private ReviewStatus _review = NullReviewStatus.Empty();
This makes the review status value equal to the nullable
object and prevents any null exceptions from using a null reference variable.
Although there are varying preferences in regards to this, I prefer this
approach in my business applications for certain object types.