15

I've come across a design pattern that's been referred to as a "Handler Pattern," but I can't find any real references to this pattern anywhere. It's basically just a one-method interface that allows you to easily extend the functionality on the back-end without making clients recompile. Might be useful for a web-service that has to handle many different types of requests. Here's an example:

public interface IHandler
{
    IDictionary<string, string> Handle(IDictionary<string, string> args);
}

The args would typically include one key like "Action" with a value that tells the implmentation what to do. Additional args can be passed in to give the impl more information. The impl then passes back an arbitrary list of args that the client "should" understand.

Is this an anti-pattern, or maybe another pattern in disguise? Is this type of design recommended?

EDIT: A little more info: The way I've seen this implemented, the "root" Handler would act as a dispatcher to other concrete handlers (maybe?). The root handler has a "HandlerResolver," which decides which concrete handler should get the message based on it's contents. Maybe it's actually like a "dispatcher" pattern, although I don't know if that's really a pattern either. I guess it could also have a chain-of-responsibility pattern in the root, that allows you to chain together a bunch of concrete handlers, then let them decide which one will handle it.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Andy White
  • 86,444
  • 48
  • 176
  • 211
  • The handler pattern abstracts a business process into some action being carried out in response to a request. This abstraction works well when the client should not have to know about the specific implementation of the handler and the action cannot be better represented by a more explicit interface. Javier is also correct in saying that its properties as a closure can be useful. It is often used in large systems to reduce coupling where there is a requirement for high extensibility. The subscriber pattern used in an Event Bus is very similar, but will invoke many handlers for a single request. – Jamie Pearcey Feb 23 '21 at 13:37

6 Answers6

10

it's the OOP way to do closures on languages that doesn't have them. it didn't have a 'pattern' name because on functional languages it's the obvious way to work. on OOP languages, OTOH, you have to do some work, so it seems a nameable idiom. 'Handler' sounds right.

(it's not a singleton, BTW)

Javier
  • 60,510
  • 8
  • 78
  • 126
2

I use it under the name of "SingletonRegistry"

See this thread

I've use it a couple of times. Specially when the actions to take are unknown upfront ( in the first phases of the design ) or the app should support extreme flexibility.

I load the dictionary either from a file or a database, and create a single instance of the class that will handle the request under certain "key".

I've found this class also searching the web for that name.

Looks like the same isn't?

Community
  • 1
  • 1
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
2

Because you had the word "Action" in your post, I am led to believe that this might be a part of the Command pattern. Check out the Wiki and search for "Handler"... maybe this will give a little more insight.

http://en.wikipedia.org/wiki/Command_pattern

Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
  • Yeah the command pattern was my first guess for what this was. I think command sort of uses something similar to this internally with the "Execute" method. – Andy White Mar 13 '09 at 04:42
1

I don't know if it's really recommended, but I've actually had to use that kind of pattern in some MATLAB applications I've written to mimic reference-like behavior for objects (which is needless now with newer versions).

Ironically, I actually called the function "handler". My object simply stored one field containing a function handle reference (@handler) and methods were just wrappers that called this function. For example, an overloaded GET function for the object would just call:

object.handler('get',...input argument list...)

I'm not sure if this is considered a "good" design choice in other languages. I chose it out of necessity, because it was the only way I came across to create reference-like behavior in MATLAB (the handler function had access to a workspace of initialized data that I wouldn't have to pass in and out of the various method calls). The newest versions of MATLAB now have a HANDLE class that can do this stuff in a much cleaner way.

gnovice
  • 125,304
  • 15
  • 256
  • 359
1

I think the goal of avoiding recompiles is much better served by a COM influenced design. What extra flexibility do you get from this:

IHandler UserHandler = ...;

Dictionary<string,string> result = UserHandler.Handle(
    new Dictionary<string, string>{
        { "Action", "AddUser" },
        { "UserName", "Joe Bloggs" },
        { "Age", "23" } });
NewUserId = Int.Parse(result["UserId"]);

over:

IUserHandler UserHandler = ...;

AddUserResult result = UserHandler.AddUser(new AddUserArgs {
    UserName = "Joe Bloggs",
    Age = 23 });
NewUserId = result.UserId;

when you can extend the actions, results, and arguments:

IUserHandler UserHandler = ...;

AddUserResult2 result = UserHandler.AddUser(new AddUserArgs2 {
    UserName = "Joe Bloggs",
    Age = 23,
    Password = "xyzzy" });
NewUserId = result.UserId;
SessionId = result.SessionId;

IUserHandler2 UserHandler2 = UserHandler as IUserHandler2;
if (UserHandler2 != null)
{
    LoginUserResult loginResult = UserHandler2.LoginUser(new LoginUserArgs {
        UserId = NewUserId,
        SessionId = SessionId,
        Password = "xyzzy" });
}
Simon Buchan
  • 12,707
  • 2
  • 48
  • 55
  • I guess the only additional flexibility you get with "Handle" is that you don't even need a specific method on the interface like "AddUser" or "LoginUser." With handle you get infinite flexibility on what the interface can do, at the cost of usability. – Andy White Mar 14 '09 at 00:08
  • That's why I had the IUserHandler2 example, showing you can add new actions as well. It's a bit more verbose overall, but I prefer the discoverability, and the clear feedback as to what version is available. Also, you can check method availability when you connect. – Simon Buchan Mar 14 '09 at 02:29
  • I agree, the "handle" method definitely sucks for discoverability – Andy White Mar 14 '09 at 07:51
0

I've seen the "Handler" classes around in legacy code bases, especially for web services. From what I've seen though, these typically turn out to be an Adapter, Facade, or some similar pattern and ends up getting called a Handler since it is handling a request.

Hazok
  • 5,373
  • 4
  • 38
  • 48