Building a chain of responsibility with delegates

Imagine that you have to write a function that verifies if there is a license available for a given clientID. Suppose that there are a couple of possibilities to find an available license. Your code would probably look like the following:

// This code verifies if the client with the given clientID is licensed
// returns the licenseID or 0 if no license is available
public Int32 IsLicensed(Int32 clientID) {
  int result = 0;

  // verify if there is already a license 'assigned' to the client
  result = IsAssigned(clientID);

  if (result == 0) {
    // find a dedicated license (license that is bound to the given client)
    result = IsDedicated(clientID);

    if (result == 0) {
      // find a nondedicated license (license that can be used by any client)
      result = IsNonDedicated(clientID);
    }
  }

  return result;
}

It’s obvious that this structures becomes more complex as the number of possible ways to get a license grows. If you look a while at the structure you’ll notice a pattern: each function (IsAssigned, IsDedicated, IsNonDedicted) verifies if there is a license availble. If the function didn’t find a license the next function is performed. If you translate this to OO you would end up with something similar to the following:

// this methods tries to find an available license for the given clientID
// returns the licenseID or 0 if no license was found
delegate Int32 FindLicenseMethod(Int32 clientID);

public class LicenseFinder {
  private FindLicenseMethod method;
  private LicenseFinder next;

  public LicenseFinder(FindLicenseMethod, method, LicenseFinder next) {
    this.method = method;
    this.next = next;
  }

  // property for the next licensefinder in the chain
  public Next {
    get { return next; }
    set { next = val; }
  }

  public Int32 GetLicense(Int32 clientID) {
    Int32 result = method(clientID);

    if (result == 0 && Next != null) {
      result = Next.GetLicense(clientID);
    }

    return result;
}

public Int32 IsLicensed(Int32 clientID) {

  LicenseFinder f = new LicenseFinder(
    new FindLicenseMethod(IsAssigned), new LicenseFinder(
    new FindLicenseMethod(IsDedicated), new LicenseFinder(
    new FindLicenseMethod(IsNonDedicated), null
  ))));

  return f.GetLicense(clientID);
}

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>