pythonでStrategyパターン
template methodパターンが継承を使ってオブジェクトのふるまいに多様性をもたらすのに対して、Strategyパターンは移譲を使います。
# coding=utf-8 class Report(object): def __init__(self, formatter, title, *text): self.formatter = formatter self.title = title self.text = text def output_report(self): self.formatter.output_report(self) class HTMLFormatter(object): def output_report(self, context): print "<html>" print "<head>" print "<title>%s</title>" % context.title print "</head>" print "<body>" for line in context.text: print "<p>%s</p>" % line print "</body>" print "</html>" class PlainTextFormatter(object): def output_report(self, context): print "***** %s *****" % context.title print "" for line in context.text: print line Report(HTMLFormatter(), u'月次報告', u"順調", u"最高の調子").output_report() # <html> # <head> # <title>月次報告</title> # </head> # <body> # <p>順調</p> # <p>最高の調子</p> # </body> # </html> Report(PlainTextFormatter(), u'月次報告', u"順調", u"最高の調子").output_report() # ***** 月次報告 ***** # # 順調 # 最高の調子 class Report2(object): """strategyクラスでなく、関数を受け取る """ def __init__(self, format_func, title, *text): self.format_func = format_func self.title = title self.text = text def output_report(self): print self.format_func(self) Report2(lambda x: "----- %s ----- \n%s" % (x.title, '\n'.join(x.text)), u"月次報告", u"順調", u"最高の調子").output_report() # ----- 月次報告 ----- # 順調 # 最高の調子
実例
djangoだとurlでのkwargs指定がStrategyパターンに近い使い方ができるかもしれない。
djangoではurls.pyでルーティングの指定をする際に、kwargsでview関数で使用するロジックを渡すことができるようになってます。
以下はパスワードリセットのview関数です。
@csrf_protect def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', email_template_name='registration/password_reset_email.html', subject_template_name='registration/password_reset_subject.txt', password_reset_form=PasswordResetForm, token_generator=default_token_generator, post_reset_redirect=None, from_email=None, current_app=None, extra_context=None):
token_generatorとしてdefault_token_generatorがデフォルトで渡されて、関数内で使用されます。
こいつを切り替えたいときはurls.pyで以下のように指定します。
url(r'^password_reset/?$', password_reset, {'token_generator': my_token_generator}, name='password_reset'),
一度指定したらずっとそれで動くのであまり動的に切り替えるって感じがしないけど