.NET Design Patterns: The Delegation Pattern

Pattern Type: Composite

Intent

The intent of the delegation pattern is simply to pass off the delegation of an operation to a different class. In many cases, this “final class” would be hooked up at compile time; however, there are a number of cases where the delegation pattern can be used to dynamically change the final destination at run time.

However it’s used, the intention is for the method being called not be the method that actually handles the request.

Description

The delegation pattern is in itself a very simple pattern. Generally, you’ll mirror the input data from the called method into an identically typed method signature.

If you don’t pass the called method off on to an identically typed method signature, you’re using the “Adapter Pattern” or maybe a derivative of the “Bridge Pattern,” both of which change the method signature called.

One place where you’ll very often find the delegation pattern used is in Async-based operations. For example, you may call a method to “Download A File,” and that method may fire off a “Task” that returns when the download has finished.

Your simple download method, to the consuming code, just looks like a simple call that returns a string. Behind the scenes, however, that simple function spins off a thread or Async call whose actual call is masked by the called method.

Diagram

Delegate1
Figure 1: Single- and double-instance Caller diagram

Description of diagram elements:

  • Caller: This is the consumer making a call to the requested method.
  • SomeMethod: This is a concrete implementation of the method being called in the enclosing class.
  • FinalMethod: This is the concrete implementation of the method being called from the SomeMethod parent; this is the delegated action.
  • IDelegationInterface: This is an interface, defining the appearance of a class containing a final method as a concrete implementation, allowing the final implementation to be changed.

Implementation in C#

To produce a single instance Delegation, you simply need a calling application, and two concrete class implementations.

namespace NutsAndBolts
{
   class Program
   {
      private static DelegationClass _delegationClass
         = new DelegationClass();

      static void Main()
      {
         _delegationClass.SomeMethod(1, 2, 3);
      }
   }
}

Code for the caller

namespace NutsAndBolts
{
   class DelegationClass
   {
      private readonly FinalClass _finalClass =
         new FinalClass();

      public void SomeMethod(int a, int b, int c)
      {
         _finalClass.FinalMethod(a, b, c);
      }

   }
}

Class representing our delegation

using System;

namespace NutsAndBolts
{
   public class FinalClass
   {
      public void FinalMethod(int a, int b, int c)
      {
         Console.WriteLine("Final method called in
            the delegation chain.");
      }
   }
}

Class representing our final concrete implementation

Implementing a multiple call is not much different, except that our delegation class derives from an interface, rather than from a concrete object. Because an interface is used, the implementation to call can, if desired, be changed at run time.

namespace NutsAndBolts
{
   public interface IDelegationInterface
   {
      void FinalMethod(int a, int b, int c);
   }
}

Delegation interface

Then, we simply create our final classes to derive from this interface, and modify the delegate caller as required.

namespace NutsAndBolts
{
   class DelegationClass
   {
      private readonly IDelegationInterface
         _finalClass;

      public void SomeMethod(int a, int b, int c)
      {
         _finalClass = new FinalClass();
         // or
         _finalClass = new FinalClass2();

         _finalClass.FinalMethod(a, b, c);
      }

   }
}

Updated Delegation Class

using System;

namespace NutsAndBolts
{
   public class FinalClass: IDelegationInterface
   {
      public void FinalMethod(int a, int b, int c)
      {
         Console.WriteLine("Final method called in
            the delegation chain.");
      }
   }
}

Updated final class implementation

using System;

namespace NutsAndBolts
{
   public class FinalClass2: IDelegationInterface
   {
      public void FinalMethod(int a, int b, int c)
      {
         Console.WriteLine("Final method 2 called
            in the delegation chain.");
      }
   }
}

Final class 2 concrete implementation

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read