views:

1192

answers:

5
+4  Q: 

"Handler" pattern?

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.

A: 

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
+1  A: 

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?

OscarRyz
A: 

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

Cory Larson
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
+1  A: 

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
A: 

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
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
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
I agree, the "handle" method definitely sucks for discoverability
Andy White