BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

Non-Virtual Interface Design Pattern

The non-virtual interface pattern is a design pattern that controls how methods in a base class are overridden. Base classes include public, non-virtual members that may be called by clients and a set of overridable methods containing core functionality.

What is the Non-Virtual Interface Pattern?

Often when you create a base class you will make its public methods virtual or abstract, allowing them to be overridden by subclasses in an inheritance hierarchy. When a base class method is overridden, the subclass' version of the method can optionally call the base class method. This allows core functionality to be created in a base class and utilised elsewhere. However, it is not mandatory for the subclass to call the base class. This means that it is possible that key functionality is not included in a subclass and that changes to a base class method may be ignored in subclasses.

The non-virtual interface pattern separates the core functionality of a base class from its public interface. The public methods of the base class are neither virtual nor abstract so cannot be overridden. The public methods call protected, virtual members in the base class, which contain core functionality that may be overridden. The functionality that must be maintained in subclasses is contained in the public members. If you decide to add extra functionality to a base class that you wish to cascade down to all subclasses, you add this to the public method. The nature of the design pattern means that you can add extra code that runs before or after the core functionality and the subclasses do not need to be recompiled.

In this article we will see the use of the non-virtual interface pattern. We will create a simple base class with an overridable method and a subclass that inherits its functionality. We will then see how additional code may be added in the base class and included within the subclass automatically.

Implementing the Non-Virtual Interface Pattern

Non-Virtual Interface Design Pattern

The UML class diagram above describes an implementation of the non-virtual interface design pattern. The items in the diagram are:

  • Base. The base class contains a public interface of non-virtual methods. In the UML, the public interface consists of the one method, named "DoWork". DoWork calls "CoreDoWork", which contains the core functionality of the method and which may be overridden by subclasses. Additional functionality may be included in DoWork and is guaranteed to be executed during calls to the public method in subclasses.
  • Derived. The derived class inherits from the base class. It cannot override DoWork so instead overrides the protected CoreDoWork method, should the functionality in the subclass be different to that in the base class.

The following shows the basic code of the template method design pattern implemented using C#.

public class Base
{
    public void DoWork()
    {
        CoreDoWork();
    }

    protected virtual void CoreDoWork()
    {
        Console.WriteLine("Base.DoWork() called");
    }
}


public class Derived : Base
{
    protected override void CoreDoWork()
    {
        Console.WriteLine("Derived.DoWork() called");
    }
}

Example Non-Virtual Interface

In this section we will create a simple example that uses the non-virtual interface design pattern. In the example is a base class that allows the saving entities to a data storage solution. A subclass is included that saves employee details. Rather than include the implementation for a database, the example outputs messages to the console that explain what the calls would do in a real situation. In this case the base class is abstract, though this is not a requirement of the design pattern.

NB: The properties in the subclass are shown using automatically implemented properties. If you are using an early version of the .NET framework you should expand these to full property declarations with backing store variables.

public abstract class Saveable
{
    public void Save()
    {
        CoreSave();
    }

    protected abstract void CoreSave();
}


public class Customer : Saveable
{
    public string Name { get; set; }
    public decimal Credit { get; set; }

    protected override void CoreSave()
    {
        Console.WriteLine("Saved customer {0} with credit limit {1}", Name, Credit);
    }
}

To test the code, add the following to the Main method of the application. This creates a customer with a name and a credit limit. When the customer is saved using the public interface, the message from the protected CoreSave method of the subclass is displayed.

Customer c = new Customer();
c.Name = "ABC Limited";
c.Credit = 100000;
c.Save();

/* OUTPUT

Saved customer ABC Limited with credit limit 100000

*/
3 September 2011