Featured image of post BP4 - Handling Chain - Learn Design Pattern From Simple Things

BP4 - Handling Chain - Learn Design Pattern From Simple Things

As a laid-off employee, you prepare for a series of top companies, and then attempt to apply one by one (only apply the next if the current is rejected) until one hires you.

Handling Chain (Chain Of Responsibility) is a behavioral design pattern: šŸ–¤šŸ–¤šŸ–¤šŸ–¤šŸ¤

What is Handling Chain?

Handling Chain is a way to set up handlers(GoogleHandler, AmazonHandler, FacebookHandler) in series to find one that can handle the input(a laid-off employee)

HandlingChain diagram

Why use Handling Chain?

  • It makes the code short and cool to use.

Question: I hate the Handling Chain, can I just use for loop then break?

Answer: Totally agree, If you find this pattern doesn’t make your code better, then ignore it.

No Chain

When to use Handling Chain?

Question: When do I use Handling Chain?

Answer: It’s like looking for a handler in a list, but the advantage of this technique is that you know that you don’t always ask from the first handler in the series, sometimes you just need to start from the middle.

Input:

  • Having handlers(GoogleHandler, AmazonHandler, FacebookHandler)
  • Having processing order based on priority (GoogleHandler > AmazonHandler > FacebookHandler)
1
# nothing here

Expected Output:

  • Input is processed(e.g. Python Dev) by the corresponding handler (Google).
1
2
3
4
5
6
Who wants a Python Dev?
  Google: I'll hire this Python Dev
Who wants a Java Dev?
  Amazon: I'll hire this Java Dev
Who wants a Golang Dev?
  The Golang Dev failed all the interviews.

How to implement Handling Chain?

Non-Handling Chain implementation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import random
from abc import ABC, abstractmethod


class Handler(ABC):
    @abstractmethod
    def handle(self, data):
        pass


class EAHandler(Handler):
    def handle(self, data):
        if "Gamer" in data:
            return f"EA: I'll hire this {data}"


class GoogleHandler(Handler):
    def handle(self, data):
        if "Python" in data:
            return f"Google: I'll hire this {data}"


class AmazonHandler(Handler):
    def handle(self, data):
        if "Java" in data:
            return f"Amazon: I'll hire this {data}"


class FacebookHandler(Handler):
    def handle(self, data):
        if random.choice([True, False]):
            return f"Facebook: I'll hire this {data}"


if __name__ == "__main__":
    ea = EAHandler()
    google = GoogleHandler()
    amazon = AmazonHandler()
    facebook = FacebookHandler()

    # build chain
    handlers = [ea, google, amazon, facebook]
    handlers.remove(ea)

    devs = ["Python Dev", "Java Dev", "Golang Dev"]
    for dev in devs:
        print(f"\nWho wants a {dev}?")
        result = None
        for handler in handlers:
            if _result := handler.handle(dev):
                result = _result
                break
        if result:
            print(f"  {result}", end="")
        else:
            print(f"  The {dev} failed all the interviews.", end="")

Handling Chain Implementation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import random
from abc import ABC, abstractmethod


class Handler(ABC):
    _next = None

    def set_next(self, handler):
        self._next = handler
        return handler

    def pass_to_next(self, data):
        return self._next.handle(data) if self._next else None

    @abstractmethod
    def handle(self, data):
        pass


class EAHandler(Handler):
    def handle(self, data):
        if "Gamer" in data:
            return f"EA: I'll hire this {data}"
        else:
            return self.pass_to_next(data)


class GoogleHandler(Handler):
    def handle(self, data):
        if "Python" in data:
            return f"Google: I'll hire this {data}"
        else:
            return self.pass_to_next(data)


class AmazonHandler(Handler):
    def handle(self, data):
        if "Java" in data:
            return f"Amazon: I'll hire this {data}"
        else:
            return self.pass_to_next(data)


class FacebookHandler(Handler):
    def handle(self, data):
        if random.choice([True, False]):
            return f"Facebook: I'll hire this {data}"
        else:
            return self.pass_to_next(data)


if __name__ == "__main__":
    ea = EAHandler()
    google = GoogleHandler()
    amazon = AmazonHandler()
    facebook = FacebookHandler()

    # build chain
    ea.set_next(google).set_next(amazon).set_next(facebook)

    devs = ["Python Dev", "Java Dev", "Golang Dev"]
    for dev in devs:
        print(f"\nWho wants a {dev}?")
        result = google.handle(dev)
        if result:
            print(f"  {result}", end="")
        else:
            print(f"  The {dev} failed all the interviews.", end="")

Source Code

Made with the laziness šŸ¦„
by a busy guy