この記事で紹介するデザインパターン
ストラテジパターン
どんなデザインパターン?
いつもどおりウェキペディアから参照
Strategy パターンは、コンピュータープログラミングの領域において、アルゴリズムを実行時に選択することができるデザインパターンである。
Strategy パターンは、アプリケーションで使用されるアルゴリズムを動的に切り替える必要がある際に有用である。Strategy パターンはアルゴリズムのセットを定義する方法を提供し、これらを交換可能にすることを目的としている。Strategy パターンにより、アルゴリズムを使用者から独立したまま様々に変化させることができるようになる。
ポイント
・ストラテジを複数用意することで、ストラテジの使用者は使用するストラテジを自由に選択、切り替えできる
・選択、切り替えの部分は移譲によって実装される
コードで理解するのが早いと思う
登場人物
・Contentクラス(使用者)
・HtmlFormatterクラス(1つめのストラテジ)
・PlainFormatterクラス。(2つめのストラテジ)
HTMLフォーマットで出力を行うアルゴリズムと、プレインテキストのフォーマットで出力を行うアルゴリズムが用意されているので、使用者は好きな方を選択して使うことでができるようなイメージ。
# Contentクラス(使用者)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Content attr_reader :title, :text attr_accessor :formatter def initialize(title, text, formatter=PlainFormatter.new) @title = title @text = text @formatter = formatter end def output @formatter.output(@title, @text) end end |
# HtmlFormatterクラス(1つめのストラテジ)
1 2 3 4 5 6 |
class HtmlFormatter def output(title, text) p "<h2>#{title}</h2>" p "<p claas=text>#{text}<p>" end end |
# PlainFormatterクラス。(2つめのストラテジ)
1 2 3 4 5 6 |
class PlainFormatter def output(title, text) p title p text end end |
コンソールから試してみる
1 2 3 4 5 6 7 8 9 10 11 12 13 |
コンテンツを作成 [19] pry(main)> content = Content.new('title', 'text') デフォルトはformatterとしてプレーンテキストが設定されているのでプレーンテキストで出力される [22] pry(main)> content.output "title" "text" やっぱりHTMLで出力したい... formatterにHTMLをセットする [23] pry(main)> content.formatter = HtmlFormatter.new HTMLで出力される [25] pry(main)> content.output "<h2>title</h2>" "<p claas=text>text<p>" |
コードで見ると理解しやすい気がする。ポイントはformatterにoutputの処理を移譲している点。
ちなみに
RailsでSNSログインなどを実装する時に使われる OmniAuth(https://github.com/omniauth/omniauth)は、それぞれgemを追加することでFacebookログイン機能(https://github.com/simi/omniauth-facebook)やTwitterログイン機能などを実装する事ができるが、これはストラテジパターンを使って実装されていると思われる。
ここに利用可能なストラテジの一覧がある。
https://github.com/omniauth/omniauth/wiki/List-of-Strategies
まとめ
・必要な処理(アルゴリズム)への切り替えが簡単にできる
・テンプレートメソッドパターンより柔軟