パンくず
リファクタリング-プログラマーの体質改善テクニック
データの再編成
State/Strategyによるタイプコードの置き換え
内容
リファクタリング名
State/Strategyによるタイプコードの置き換え
適用ケース要約
クラスのふるまいに影響を与えるタイプコードが使われており、タイプコードは実行時に変更される。
適用内容要約
タイプコードをState/Strategyオブジェクトに取り換える
適用詳細
基本的には「クラスによるタイプコードの置き換え」、「サブクラスによるタイプコードの置き換え」と同じ考えだが、
置き換える対象のタイプコードが実行時に変化する場合はこちらのリファクタリングを適用する。
状態を扱うならState、アルゴリズムを扱うならStrategyを使用します。
サンプル
時刻によって値段が変わる定食屋さんを実装します
12時台、13時台はランチ料金で2割引き。
22時から24時は深夜料金で2割増し。
その他は通常料金とします。
サンプルコード
# encoding: Shift_JIS class Diner LUNCH_TIME_PRICE_RATE = 0.8 NIGHT_TIME_PRICE_RATE = 1.2 DEFAULT_PRICE_RATE = 1 def get_price(base_price) rate=DEFAULT_PRICE_RATE case Time.new.hour when 12..13 rate=LUNCH_TIME_PRICE_RATE when 22..24 rate=NIGHT_TIME_PRICE_RATE else end return base_price*rate end end diner = Diner.new base_price=1000 puts diner.get_price(base_price)
# encoding: Shift_JIS class Diner def get_price(base_price) return DinerPriceCalculator.get_instance.calculate_price(base_price) end end class DinerPriceCalculator DEFAULT_PRICE_RATE = 1.0 def self.get_instance() case Time.new.hour when 12..13 return LunchDinerPriceCalculator.new when 22..24 return NightDinerPriceCalculator.new else return self.allocate end end def get_rate() return DEFAULT_PRICE_RATE end def calculate_price(base_price) base_price*get_rate() end end class LunchDinerPriceCalculator < DinerPriceCalculator LUNCH_TIME_PRICE_RATE = 0.8 def get_rate() return LUNCH_TIME_PRICE_RATE end end class NightDinerPriceCalculator < DinerPriceCalculator NIGHT_TIME_PRICE_RATE = 1.2 def get_rate() return NIGHT_TIME_PRICE_RATE end end diner = Diner.new base_price=1000 puts diner.get_price(base_price)
出力(共通)
12時から13時台に実行した場合
800.0
22時から24時台に実行した場合
1200.0
その他の時間に実行した場合
1000.0
補足
今回はサンプルなので定数を返す部分しか差異がありませんが、
このような場合は基底クラスに一本化するのが好ましいです。
※次のリファクタリング手法である
「フィールドによるサブクラスの置き換え」
の適用対象にあたります