# Chain of responsibility pattern

class ReportFormat(object):
PDF = 0
TEXT = 1

class Report(object):
"""Strategy context."""

def __init__(self, format_):
self.title = 'Monthly report'
self.text = ['Things are going', 'really, really well.']
self.format_ = format_

class Handler(object):

def __init__(self):
self.nextHandler = None

def handle(self, request):
self.nextHandler.handle(request)

class PDFHandler(Handler):

def handle(self, request):
if request.format_ == ReportFormat.PDF:
self.output_report(request.title, request.text)
else:
super(PDFHandler, self).handle(request)

def output_report(self, title, text):
print '<html>'
print '    <title>%s</title>' % title
print '  <body>'
for line in text:
print '    <p>%s</p>' % line
print '  </body>'
print '</html>'

class TextHandler(Handler):

def handle(self, request):
if request.format_ == ReportFormat.TEXT:
self.output_report(request.title, request.text)
else:
super(TextHandler, self).handle(request)

def output_report(self, title, text):
print 5*'*' + title + 5*'*'
for line in text:
print line

class ErrorHandler(Handler):

def handle(self, request):
print "Invalid request"

if __name__ == '__main__':
report = Report(ReportFormat.TEXT)
pdf_handler = PDFHandler()
text_handler = TextHandler()

pdf_handler.nextHandler = text_handler
text_handler.nextHandler = ErrorHandler()

pdf_handler.handle(report)


O/P:

*****Monthly report*****
Things are going
really, really well.


In my opinion, this is abuse of the Chain-of-responsibility Pattern. It is completely surprising that pdf_handler.handle(report) would generate a text report instead.

The Wikipedia example for Chain-of-responsibility is a logger. As the message passes through the chain, each logger may choose to do something with it (write to standard output, send e-mail, etc.) depending on the verbosity level.

Another example of Chain-of-responsibility is the filter mechanism in Apache HTTPD. Each input or output filter in the chain can alter the request or response.

Your use case is different: you only want to generate one kind of report. For that, use a subtly different design: the Strategy Pattern. Basically, just do the simplest thing that could work:

• Each kind of handler defines a handle(self, request) method.
• If you want a text report, then call TextReport().handle(request).
• No, its not an abuse. See this description – vivek May 25 '14 at 7:33
• Yes, it is abuse, as I just explained. As your article states, Chain of Responsibility "[avoids] coupling the sender of a request to its receiver by giving more than one object a chance to handle the request." But you have no reason to let multiple objects handle the request. I've given examples of where a chain would be appropriate; your problem does not fit that pattern. – 200_success May 25 '14 at 7:40
• The request should be handled by any on object, read it again. – vivek May 26 '14 at 17:36
• +1 I totally agree with your answer, but rereading both articles linked here I see the examples use the same design where each link has a reference to the next link in the chain. By moving the chain creation into a separate method, you don't realize that the first link in the chain is being referenced by clients directly. Clients think they have a generic ReportHandler when in reality they hold the PDFHandler. – David Harkness May 26 '14 at 19:22

I would not use Chain of Responsibility to solve this problem. For every request, a single handler is chosen based on the same property: it's output format. For that you can use a simple dispatch table: a dict mapping each output format to its handler. There's no point asking each handler if it can handle the request.

Update: As usual, the Portland Pattern Repository has some good historical discussion of this pattern, specifically when not to use it:

Do not use Chain of Responsibility when each request is only handled by one handler, or, when the client object knows which service object should handle the request.

Note: Report and ReportFormat are unchanged from the OP and omitted for brevity.

class ReportDispatcher(object):
def __init__(self):
self.reports = {}

self.reports[report.format] = report;

def handle(self, request):
report = self.reports[request.format_]
if report:
report.handle(request)
else
print "Invalid request"

class Handler(object):

def __init__(self, format):
self.format = format

def handle(self, request):
print "subclass responsibility"

class PDFHandler(Handler):

def __init__(self):
super(PDFHandler, self).__init__(ReportFormat.PDF)

def handle(self, request):
print '<html>'
print '    <title>%s</title>' % request.title
print '  <body>'
for line in request.text:
print '    <p>%s</p>' % line
print '  </body>'
print '</html>'

class TextHandler(Handler):

def __init__(self):
super(TextHandler, self).__init__(ReportFormat.TEXT)

def handle(self, request):
print 5*'*' + request.title + 5*'*'
for line in request.text:
print line

if __name__ == '__main__':
reports = ReportDispatcher()