4 minute read

GoF Numbering : 13
Category : Behavioral Pattern
Readings : Wikipedia, DigitalOcean, cs.unc.edu, Refactoring.guru

In One Sentence

Propagate handling of the data or action into inter-connected handlers.

You are playing board game, telestrations. Sketch 5 seconds(data or action) and pass the book to the next person(handler) you know. If you don’t have to, finish the game.

Problem

Let’s start from the naive idea of handling very complicated logic in only one function. Or let’s say the program got crashes and you got a really long error message. Now you need to process them in a function with 500 lines.

Can you even imagine maintaining that code without extracting functions or splitting them?

No way.

Now you checked which spots can be refactored. And you found

  • Most of codes are treating same data chunk and use only they care about
  • Some of them are actually not needed all the time. They are enabled very dynamically based on users input, decisions or settings.
    • ex) You enabled the function with a boolean flag in your setting option.
  • Data receiving and processing parts are very coupled. But seems they have no reason to know each other.

At the end, you refactored the handling codes into several classes which do specific tasks.

  • Send an email to the developer team.
  • Write the log message into a .log file.
  • Post the issue on github.
  • Send slack notification.

After a day, you get super annoyed by tons of slack notification. You decided to turn off slack notification and the SMTP as well. Now the system only logs into a file and posts it on the github issue page. You just dynamically changed log handling pipeline.

What COR Pattern is trying to solve?

  • In runtime, dynamically choose Handlers and order of handling
    • Choose which handlers should act based on settings or situations. Even there is a chance that the input didn’t get handled at all.
  • Decoupled request senders and handlers
  • Create a handling procedure under your control in a cleaner way

Each handler does not know each other, even senders. They are completely abstracted lego blocks and you should be able to attach & detach at anytime.

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. cs.unc.edu

Keep in mind

  • A request better remain unmodified while sailing the handler chains. If it does, you will end up creating a coupling in between handlers and lead to unintended behaviors.

    This aspect also implies each handler should be able to process a request individually without a chain.

    Counter of this example will be ATM Cash Dispenser idea. You have a total amount of dollar you want to withdraw. Then, each cash dispenser should subtract the amount of the requested data.

  • You better prepare exception handlers which works like a finally syntax in try-catch block for unhandled requests. Since all handlers do not know each other but the linked handler, they even have no idea the request will be successfully handled at least one time.

Code Example - Logger

C++ Version

Wikipedia’s Logger Example chains each Logger to demonstrate the pattern’s aspect - Handler knows the next handler and toss the request to the next. But in this example, each logger will not know each other but the LogManager will handle the order of calls.

Code Example - Did you find?

  • LogManager will be often implemented as a Singleton because message logging is enough through only one manager.

  • Each Logger could have Factory Method to generate a Logger class with some setup such as SMTP setting, File name, OAuth, etc. Each logger also can be Singletons as well.

  • LogManager is using Iterator Pattern (sort of…😅 in this example) to retrieve each Logger in the container without knowing that.

Example Ideas

  • ATM Cash Dispenser

    Depends on your money withdrawal options, you can choose each amount of $20, $10, $5. Each dollar can be demonstrated by separate dollar dispensing handlers.

  • Email Filter

    To avoid and block fraud or spam emails or even word filtering(?), you can setup several filter walls in between SMTP server and the endpoint. For each step handlers will go through the email information and check whether it needs to be filtered or not.

  • UI Input Event Handling

    When we get Input events, they should be handled from top to bottom of handlers. Each handler will tell the input better get handled by them or not. Think about 3D rendering view with some UI buttons and panels. If you click UI buttons, 3D render should not respond to your action.

  • Tech Support Center Call 😭

    It’s round a round a round a round a round. The automated responder will let you choose a menu from one of the frequently asked options and depends on the menu, each menu handler will guide you to the other section and you will run into another handlers of handlers of handler.

Leave a comment