君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

劇的ビフォ◯アフターで学ぶデザインパターン(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パターンと同じです。

違うのは状態か戦略かという違い。

個人的には呼び方を一緒にしてしまってもいい気がします。。