君は心理学者なのか?

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

劇的ビフォ◯アフターで学ぶデザインパターン(state編:after)

前回のソースコードをstateパターンを使用して書き換えていく

f:id:karoten512:20171019233939p:plain

前回のソースコードを見てみると、

状態と、その状態の時の振る舞いが描かれていることがわかります。

図の例なら、「HAPPY」「HAPPY時の振る舞い(hello, goodbye)」です。

これを状態クラスとして書き出します。

状態クラス(状態時の振る舞いを持ったクラス)を作成

# たのしい時
class HappyState
  def self.hello
    puts 'hello!!!'
  end

  def self.goodbye
    puts 'goodbye!!!'
  end
end

他の2つの状態についても状態クラスとして書き出します。

# 通常
class NormalState
  def self.hello
    puts 'hello'
  end

  def self.goodbye
    puts 'goodbye'
  end
end


# 風邪引いた時
class ColdState
  def self.hello
    puts 'hello...'
  end

  def self.goodbye
    puts 'goodbye...'
  end
end

Humanクラスが状態クラスを持つようにする

そして、Humanクラスでは先ほどの状態クラスをstateとして保持するようにします。

class Human

  # その人心理的状態
  attr_accessor :state

  def initialize(state = NormalState)
    # 引数が渡ってきていない場合、デフォルトでNormalStateにする
    state = state
  end

  # 挨拶をさせる(stateクラスにメッセージを送る)
  def hello
    state.hello
  end

  # 挨拶をさせる(stateクラスにメッセージを送る)
  def goodbye
    state.goodbye
  end

  # 状態クラスをセットする
  def set_state(state)
    state = state
  end

end

if文による条件分岐がなくなり、スッキリしましたね。

Humanクラス使用時

human = Human.new()
human.hello
human.goodbye

human.set_state(ColdState)
human.hello
human.goodbye

human.set_state(HappyState)
human.hello
human.goodbye

結果

hello
goodbye
hello...
goodbye...
hello!!!
goodbye!!!

仕様変更

さて、これでstateパターンへの書き換えが終了しました。

ここで例の仕様変更です。

上司「恋に落ちた状態も用意してくれ」

stateパターンを使用しない場合、4行の修正が必要になりました。

stateパターンを使用する場合、既存のソースコードはどのように変更されるでしょうか。

結論

既存のソースコード(Human, ~Stateクラス)は変更されません

新規に以下のクラスが追加されるだけです。

# 恋におちた時
class FallInLoveState
  def self.hello
    puts 'hello,  love you!'
  end

  def self.goodbye
    puts "Don't leave me alone..."
  end
end

このクラスを使用するときは、先ほどと同じように

human.set_state(FallInLoveState)
human.hello
human.goodbye

とするだけです。

まとめ

stateパターンを使用することにより、オブジェクトの状態をクラスとして分離することが出来ます。

そうすると、新しい状態を追加した際に、既存のソースコード 一切変更せずに すみ、

新しい状態のクラスを追加するだけですみます。

縮めたのたった4行だけかよ。って思うかもしれません。

たしかにそうです笑

ただ、状態が大量にある場合や複雑な条件分岐が行われる場合、

stateパターンを用いるとソースコードが明快になることが多いです。