A A
[Design Pattern] Chain of Responsibility

Chain of Responsibility Pattern

Chain of Responsibility Pattern์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋“ค์—๊ฒŒ ๋ถ€์—ฌํ•จ์œผ๋กœ์จ ๊ทธ๋“ค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ์—†์• ์ฃผ๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

  • ๋ณต์ˆ˜์˜ Object๋ฅผ ์‚ฌ์Šฌ์ฒ˜๋Ÿผ ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด, ๊ทธ ์˜ค๋ธŒ์ ํŠธ์˜ ์‚ฌ์Šฌ์„ ์ฐจ๋ ˆ๋Œ€๋กœ ๋Œ์•„๋‹ค๋‹ˆ๋ฉด์„œ ๋ชฉ์ ํ•œ Object๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  • responsibility ๊ฐœ๋…์„ ๊ฐ–๋Š” ๋ชจ๋“ˆ๋“ค์— ์ฒด์ธ์„ ๋งŒ๋“œ๋Š” Pattern ์ž…๋‹ˆ๋‹ค.

  • chain of responsibility pattern์ด ์•„๋‹Œ ๊ฒฐ์ œ ์˜ˆ์ œ
    • ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ๊ฒฐ์ œ ์š”์ฒญ์„ ๋ฐœํ–‰ ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฒฐ์ œ ์š”์ฒญ ์•ˆ์—๋Š” ๊ฒฐ์ œ๋ฐฉ๋ฒ•๊ณผ ๊ธˆ์•ก์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์—๋Š” cash, credit card, debit card ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๊ฒฐ์ œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ ์ƒˆ๋กœ์šด ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ฝ”๋“œ์˜ ๊ธธ์ด๊ฐ€ ๊ธธ์–ด์ง€๊ณ  ๋ณต์žกํ•ด์ง‘๋‹ˆ๋‹ค.

  • ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ๋ชจ๋“ˆ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
    • Cash Handler, Credit Card Handler, Debit Card Handler๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฐ Handler๋ฅผ ์ฒด์ธ์œผ๋กœ ๋ฌถ์Šต๋‹ˆ๋‹ค.
Cash Handler๋ฅผ ๋งŒ๋‚˜๊ณ  ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์ด Cash์ธ ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  ๋ฐ”๋กœ ๊ฒฐ์ œ๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์ด Debit Card์ด๋ฏ€๋กœ Cash Handler, Credit Card Handler๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ๋‹ค์Œ Handler์—๊ฒŒ ๋„˜๊ธฐ๊ณ  ๊ฒฐ๊ตญ Debit Card Handler๊ฐ€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Example: ๊ฒฐ์ œ ์‹œ์Šคํ…œ

Base class

class Handler:
    def __init__(self):
        self.next_handler = None

    def setNext(self, handler):
        self.next_handler = handler

    def handle(self, req):
        if self.next_handler:
            return self.next_handler.handle(req)
        print("All handlers failed")
        return None
  • __init__
    • ๋‚ด๋ถ€์— ๋‹ค์Œ Handler๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” next_handler ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  • setNext()
    • ๋‹ค์Œ Handler์ธ next_handler๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • handle()
    • ๊ฒฐ์ œ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์‹คํ–‰์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
    • Argument๋กœ request ์ •๋ณด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๋‹ค์Œ Handler๊ฐ€ ์กด์žฌํ•˜๋ฉด next_handler์˜ handle ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    • ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, None์„ Return ํ•ฉ๋‹ˆ๋‹ค.

 

Cache Handler

class CashHandler(Handler):
    def handle(self, req):
        if req['method'] == 'cash':
            print(f"processing cash {req['amount']} won")
        else:
            print(f"CashHandler cannot process")
            super().handle(req)

class CreditCardHandler(Handler):
    def handle(self, req):
        if req['method'] == 'creditCard':
            print(f"processing creditCard {req['amount']} won")
        else:
            print(f"CreditCardHandler cannot process")
            super().handle(req)

class DebitCardHandler(Handler):
    def handle(self, req):
        if req['method'] == 'debitCard':
            print(f"processing debitCard {req['amount']} won")
        else:
            print(f"DebitCardHandler cannot process")
            super().handle(req)
  • CashHandler - handle()
    • Base class์˜ handleํ•จ์ˆ˜๋ฅผ override ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฒฐ์ œ ๋ฐฉ๋ฒ•์ด 'cash'์ผ ๊ฒฝ์šฐ, ๊ฒฐ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    • 'cash'๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ, ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ถœ๋ ฅ ํ›„ Base class์˜ handle()ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฅด๊ธฐ ์œ„ํ•ด super().handle๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  req๋ฅผ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค. (๋‹ค์Œ Handler์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋Š” ๋ถ€๋ถ„)
  • CreditCardHandler
    • CashHandler์™€ ๋™์ผํ•œ ๋ฐฉ์‹
    • Method๊ฐ€ "creditCard"์ผ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
  • DebitCardHandler
    • CashHandler์™€ ๋™์ผํ•œ ๋ฐฉ์‹
    • Method๊ฐ€ "debitCard"์ผ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ

 

cash_handler = CashHandler()
creditcard_handler = CreditCardHandler()
debitcard_handler = DebitCardHandler()

cash_handler.setNext(creditcard_handler)
creditcard_handler.setNext(debitcard_handler)
  • ๊ฐ Handler์˜ Object๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • setNext ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์„ธ ๊ฐœ์˜ Handler๋ฅผ ์ฒด์ธ์ฒ˜๋Ÿผ ๋ฌถ์Šต๋‹ˆ๋‹ค.

 

payment = {
    "method": "cash",
    "amount": 10000
}

cash_handler.handle(payment)
  • ๊ฒฐ์ œ ๋ฐฉ์‹์ด "cash"์ธ payment๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ๋ชจ๋“ˆ์ธ CashHandler์—์„œ ๋ฐ”๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

payment = {
    "method": "debitCard",
    "amount": 10000
}

cash_handler.handle(payment)
  • ๊ฒฐ์ œ ๋ฐฉ์‹์ด "debit card"์ธ payment๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • CashHandler์™€ CreditCardHandler์—์„œ๋Š” ์ฒ˜๋ฆฌ๋ฅผ ๋ชปํ•˜๊ณ  DebitCardHandler์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

 

payment = {
    "method": "paypal",
    "amount": 10000
}

cash_handler.handle(payment)
  • ๊ฒฐ์ œ ๋ฐฉ์‹์ด "paypal"์ธ payment๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์„ธ ๊ฐ€์ง€ Handler ๋ชจ๋‘ ํ•ด๋‹น ์•ˆ๋˜๋ฏ€๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋… ํ™•์žฅ

๋“ฑ์žฅ์ธ๋ฌผ

  • Handler: ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • '๋‹ค์Œ ๋‹ด๋‹น์ž'๋ฅผ ์ค€๋น„ํ•ด ๋‘๊ณ  ์ž์‹ ์ด ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ์š”๊ตฌ๊ฐ€ ๋‚˜์˜ค๋ฉด ๊ทธ ๋‹ด๋‹น์ž์—๊ฒŒ ๋– ๋„˜๊ธฐ๊ธฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  '๋‹ค์Œ ๋‹ด๋‹น์ž'๋„ Handler ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ConcreteHandler: ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • Client: ์ตœ์ดˆ์˜ ConcreteHandler ์—ญํ• ์— ์š”๊ตฌํ•˜๋Š” ์ผ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ๊ณผ ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์‚ฌ๋žŒ์„ ์œ ์—ฐํ•˜๊ฒŒ ์—ฐ๊ฒฐ

  • Client๋Š” ์ตœ์ดˆ๋กœ ๋งŒ๋‚˜๋Š” ๋‹ด๋‹น์ž์—๊ฒŒ ์š”๊ตฌํ•˜๋ฉฐ, ๋’ท์ผ์€ ์‚ฌ์‹ค ์•ˆ์œผ๋กœ ๊ทธ ์š”๊ตฌ๊ฐ€ ์ „๋‹ฌ๋˜์–ด ์ ์ ˆํ•œ ๋‹ค๋ฅธ ๋‹ด๋‹น์ž์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ๋งŒ์•ฝ Chain of Responsibility๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ‘์ด ์š”๊ตฌ๋Š” ์ด ๋‹ด๋‹น์ž๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค’๋ผ๋Š” ์ •๋ณด๋ฅผ ๋ˆ„๊ตฐ๊ฐ€ ์ค‘์•™์ง‘๊ถŒ์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ‘์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ’์—๊ฒŒ ๊ฐ–๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ํ˜„๋ช…ํ•œ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.
    • ์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋‹ด๋‹น์ž๋“ค์˜ ์—ญํ•  ๋ถ„๋‹ด๊นŒ์ง€ ์ž์„ธํ•˜๊ฒŒ ์•Œ์•„์•ผ ํ•œ๋‹ค๋ฉด ๋ถ€ํ’ˆ์œผ๋กœ์„œ์˜ ๋…๋ฆฝ์„ฑ์ด ํ›ผ์†๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๋™์ ์œผ๋กœ ์‚ฌ์‹ค์˜ ํ˜•ํƒœ๋ฅผ ๋ณ€๊ฒฝ

  • ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ConcreteHandler ์—ญํ• ์˜ ์˜ค๋ธŒ์ ํŠธ ๊ด€๊ณ„๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ์ƒํ™ฉ์ด ์žˆ์„ ๋•Œ, ConcreteHandler ์—ญํ• ์„ ์žฌํŽธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋งŒ์•ฝ, CoR ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋žจ ์•ˆ์— ‘์ด ์š”๊ตฌ๋ผ๋ฉด ์ด ๋‹ด๋‹น์ž’๋ผ๋Š” ๋Œ€์‘ ๊ด€๊ณ„๊ฐ€ ๊ณ ์ •์ ์œผ๋กœ ๊ธฐ์ˆ ๋˜์–ด ์žˆ์œผ๋ฉด ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘์— ์ฒ˜๋ฆฌ์ž๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ž์‹ ์˜ ์ผ์— ์ง‘์ค‘

  • ๋– ๋„˜๊ธฐ๊ธฐ๋Š” ๋ถ€์ •์  ์˜๋ฏธ๊ฐ€ ๊ฐ•ํ•˜์ง€๋งŒ, ๊ฐ ์˜ค๋ธŒ์ ํŠธ๋Š” ์ž์‹ ์˜ ์ผ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ๊ฐ์˜ ConcreteHandler ์—ญํ• ๋“ค์ด ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๊ฒƒ๋“ค์ด ๊ณ ์œ ํ•œ ๋‚ด์šฉ์œผ๋กœ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋– ๋„˜๊ธฐ๊ธฐ๋กœ ์ธํ•˜์—ฌ ์ฒ˜๋ฆฌ๊ฐ€ ์ง€์—ฐ๋˜์ง€ ์•Š์„๊นŒ?

  • ํ•ด๋‹น ๊ตฌ์กฐ๋Š” ํ‹€๋ฆผ์—†์ด ์œ ์—ฐ์„ฑ์€ ๋†’์„์ง€ ๋ชจ๋ฅด์ง€๋งŒ ์ฒ˜๋ฆฌ๊ฐ€ ์ง€์—ฐ๋  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.
  • ๋ˆ„๊ฐ€ ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ง€ ๋ฏธ๋ฆฌ ์ •ํ•ด์ ธ ์žˆ๊ณ  ๊ทธ ๋‹ด๋‹น์ž๊ฐ€ ๋ฐ”๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๋น„๊ตํ•˜๋ฉด ์ง€์—ฐ๋˜๋Š” ๋ถ€๋ถ„๋„ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ผ์ข…์˜ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๋กœ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์š”๊ตฌ์ž์™€ ์ฒ˜๋ฆฌ์ž์˜ ๊ด€๊ณ„๊ฐ€ ๊ณ ์ •์ ์ด๊ณ  ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ์ƒ๋‹นํžˆ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ CoR ํŒจํ„ด์„ ๊ตณ์ด ์‚ฌ์šฉํ•  ์ด์œ ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.