##はじめに
構造がきれいな設計のために、デザインパターンを再学習しています。
今回はStrategyパターンを扱います。
ちなみに、きれいなコードとはデザインパターンのような構造に関するものと、
リーダブルコードに書いてあるような、読みやすコードの記述方法の2つからなると考えています。
##環境
Ruby 2.3.0
##概要
振る舞いに関するパターンのひとつで、アルゴリズムを交換できるよう実装します。
「別々のオブジェクトにアルゴリズムを引き出す」テクニックとのこと。
また、Strategyとは英語で「戦略」という意味です。
Strategyパターンを適用するとifをなくすことができます。
コンテキストにもよるので、ケースバイケースですが、
ifなどで分岐してしまうと、複雑になり、可読性も下がります。
理想はifができるだけ少ないプログラムです。
###コード1
コード1はクラスの継承による実装です。
継承を使用すると、他に継承できなくなる(多重継承はできない)のと、
アルゴリズムごとにクラスを用意する必要があることがイマイチな気がします。
#継承(抽象)クラスを使用したstrategy
class AbstractFormatter
def output
raise "Abstract Method"
end
end
class TextFormatter < AbstractFormatter
def output
puts "text"
end
end
class HtmlFormatter < AbstractFormatter
def output
puts "html"
end
end
class XMLFormatter < AbstractFormatter
def output
puts "XML"
end
end
text = TextFormatter.new
text.output # => text
html = HtmlFormatter.new
html.output # => html
xml = XMLFormatter.new
xml.output # => xml
###コード2
コード2はProcオブジェクトを使用した実装で、
よりRubyらしく、アルゴリズムの切り替えも実装できています。
#lambdaを使用したstrategy
class Formatter
def initialize(&formatter)
@formatter = formatter
end
def switch_formatter(&formatter)
@formatter = formatter
end
def output
@formatter.call
end
end
text = -> { puts "text" }
html = -> { puts "html" }
xml = -> { puts "xml" }
formatter = Formatter.new &html
formatter.output # => text
formatter.switch_formatter &text
formatter.output # => html
formatter.switch_formatter &xml
formatter.output # => xml
##参考