Null Object – Designed to act as a default value of an object.

From Design Pattern – Behavioral Patterns

Structure

Null object pattern – Class diagram UML

Applicability

Objects require a collaborator which the null object pattern doesn’t introduce that makes use of a collaboration already exists. Some collaborator instance doesn’t do any things. Its pattern can reduce using null keyword times.

Pros and Cons

PROS

  • These are the class hierarchy so that a null object can be used instead of the natural object.
  • It makes the client code a lot cleaner and more straightforward, and the client no longer has to worry about getting a null reference which will always get a reference to a valid object, even if that objects do nothing.
  • It can also improve the code speed up by unnecessary if checks.

CONS

  • It can waste memory if there are a lot of null objects, which solve that one usually implements the null object as a singleton.
  • The “do-nothing” behavior may not be well defined. If the programs have multiple clients, they must all “agree” on what a defined behavior is/or need to implement different null objects.
  • Sometimes, the null objects must be replaced by a real object that can be implemented by using the state design pattern.

How to Implement

#1 Basic Sample

The primary sample has three kinds of examples because these are based on the .Net framework version. One instance uses the “virtual” keyword to implement its pattern. Another instance uses the generic type, and class construction mechanisms then implement the null object pattern. Other instances use the new C# version to implement its, which is easy and sample to do it

  • Virtual keyword sample
static void Main(string[] args)
{
	Order order = new Order();
	Customer customer = new Customer();
	customer = order.customer ?? new NullCustomer();
    
	Console.ReadKey();
}

internal class Order
{
	public Customer customer { get; set; }
}

internal class Customer
{
	public virtual bool IsNull { get; set; }

	public virtual string Name { get; set; }

	public virtual string Note { get; set; }

	public virtual NullPlan NullPlan() => new NullPlan();
}

internal class NullPlan
{ }

public sealed class NullCustomer : Customer
{
	public override bool IsNull
	{
		get { return true; }
	}

	public override string Name => "Defult value";

	public override string Note => "Defult value";

	public override NullPlan NullPlan() => new NullPlan();
}
  • Generic type and class construction mechanisms
static void Main(string[] args)
{
	Order order = new Order();
	Customer customer = new Customer();

	BaseClass<Customer> baseClass = new BaseClass<Customer>();
	customer =  order.customer ?? new NullObjectPattern<Customer>(new object[] { true, "Default value", "Default value" }).Instance;

	Console.ReadKey();
}

internal class Order
{
	public Customer customer { get; set; }
}

internal class Customer
{
	public Customer() { }
	public Customer(bool _isnull, string _name, string _note)
	{
		IsNull = _isnull;
		Name = _name;
		Note = _note;
	}

	public virtual bool IsNull { get; set; }

	public virtual string Name { get; set; }

	public virtual string Note { get; set; }

	public virtual NullPlan NullPlan()
	{
		return new NullPlan();
	}
}

internal class NullPlan
{ }

internal class BaseClass<T> where T : class
{
	public virtual T Instance { get; set; }
}

public sealed class NullObjectPattern<T> : BaseClass<T> where T : class
{
	private object[] ObjectArry { get; set; } = new object[] { };

	public NullObjectPattern(object[] _object)
	{
    		ObjectArry = _object;
	}

	public NullObjectPattern() { }

	public override T Instance => (T)Activator.CreateInstance(typeof(T), ObjectArry);
}
  • The new version of C#
static void Main(string[] args)
{
	Order order = new Order();
	Customer customer = new Customer();
	customer = order.customer ?? new Customer();
    
	Console.ReadKey();
}

internal class Order
{
	public Customer customer { get; set; }
}

internal class Customer
{
	public virtual bool IsNull { get; set; } = false;

	public virtual string Name { get; set; } = "Default value";

	public virtual string Note { get; set; } = "Default value";

	public virtual NullPlan NullPlan()
	{
		return new NullPlan();
	}
}

internal class NullPlan
{ }

#2 Web Application Project

Step 1 Creating the entity data transfer object(DTO) class and the new data transfer object class, which includes the entity data transfer object class statement, means letting both types have a relationship.

Fig 1 EntityDto class file source code.
Fig 2 NullObjectDto class file source code.

Step 2 Create the sealed class file in the entity DTO class files, which lets the “Virtual keyword methods” be implemented in the web project situation.

Fig 3 IsNullEntityDto class source code in the EntityDto class files.

Step 3 This step is for the generic method of the null object pattern, which must create two class files. These files let its design can implement in web projects.

Fig 4 BaseClass class file source code.
Fig 5 IsNullObject class file source code

Step 4 Create the interface class and the service class files about the null object pattern in the Core project, then add the three kinds of methods of the null object pattern in the operation block. Adding the object records these executing results.

Fig 6 INullObject interface class file source code
Fig 7 NullObjServices class file source code.

Step 5 Create the null object pattern-related files in the web projects, such as view files and the controller files. Register the null object pattern’s interface class files and the services class file in the startup.cs file.

// Null object pattern
services.AddScoped(typeof(INullObject), typeof(NullObjServices));

Reference

1 Comment

Leave a Reply