劇的ビフォ◯アフターで学ぶデザインパターン(strategy編:after)
前回のソースコードをstrategyパターンを使用して書き換えていく
前回のソースコードから、戦略に関する部分についてクラスで切り出します。
戦略クラス(特定戦略時の振る舞いを持ったクラス)を作成
# ガンガン行こうぜのとき class StrategyGangan def self.attack puts 'こうげきまほうをつかった!' end end
他の2つの戦略についてもクラスとして分離します。
# じゅもんつかうな class StrategyNotUseJumon def self.attack puts 'ふつうにこうげきした!' end end # いのちをだいじに class StrategyInochiDaijini def self.attack puts 'かいふくまほうをつかった!' end end
Heroクラスが戦略クラスを持つようにする
そして、Heroクラスでは先ほどの戦略クラスをstrategyとして保持するようにします。
class Hero attr_accessor :strategy def initialize(strategy = StrategyGangan) # 引数が渡ってきていない場合、デフォルトでガンガンいこうぜ @strategy = strategy end # 攻撃をさせる def action strategy.attack end # 作戦切り替え def change_strategy(strategy) @strategy = strategy end end
前回のソースコードと比較すると、相当スッキリしています。
Heroクラス使用時
hero = Hero.new() hero.action hero.change_strategy(StrategyNotUseJumon) hero.action hero.change_strategy(StrategyInochiDaijini) hero.action
結果
こうげきまほうをつかった! ふつうにこうげきした! かいふくまほうをつかった!
仕様変更
さて、これでstrategyパターンへの書き換えが終了しました。
ここで例の仕様変更です。
上司「バッチリがんばれを追加な」
strategyパターンを使用した場合、変更箇所はどう変わるでしょうか。
比較
- strategyパターンを使用しない場合
3行
- strategyパターンを使用する場合
0行
既存のソースコード(Human, ~Strategyクラス)は変更されません 。
新規に以下のクラスが追加されるだけです。
class StrategyBachiri def self.attack puts 'たまにはかいふくするぜ!' end end
このクラスを使用するときは、先ほどと同じように
hero.change_strategy(StrategyBachiri)
hero.action
とするだけです。
まとめ
strategyパターンを使用することにより、戦略をクラスとして分離することが出来ます。
新しい戦略を追加した際に、既存のソースコードを 一切変更せずに すみ、
新しい状態のクラスを追加するだけですみます。
ちなみにやっていることはstateパターンと同じです。
違うのは状態か戦略かという違い。
個人的には呼び方を一緒にしてしまってもいい気がします。。