LoginSignup
2

More than 5 years have passed since last update.

【デザインパターン】 Stateパターン

Last updated at Posted at 2015-08-09

概要

状態を表すオブジェクトを導入することで、オブジェクトの内部状態が変化した時に、オブジェクトが振る舞いを変えるようにするパターン

以下の3種類のクラスからなる
1. Contextクラス(クライアントに必要なインターフェイスを定義し、状態を表す3.のインスタンスを保持する)
2. Stateクラス(1.の個々の状態に関する振る舞いをカプセル化するためのインターフェイスを定義)
3. ConcreteStateクラス(1.のある状態に関する振る舞いを実装)

具体例と実装

自動空調を例にすると、

上記1~3はそれぞれ

  1. リモコンクラス(RemoteControllerクラス、空調の運転状態を切り替える)
  2. 温度調節クラス(TemperatureControlクラス、運転状態に共通の振る舞いを定義)
  3. 冷房クラス、暖房クラス、エコモードクラス(Coolingクラス、Heatingクラス、EcoModeクラス、冷房、暖房、エコモードそれぞれの運転状態での振る舞いを実装)

が対応する。
コードの詳細は以下

remote_controller.rb
class RemoteController
  def initialize(drive_mode)
    @drive_mode = drive_mode
  end

  def drive
    @drive_mode.set_temperature
    @drive_mode.drive
  end

  def set_drive_mode(drive_mode)
    @drive_mode = drive_mode
  end
end
temperature_control.rb
class TemperatureControl
  def initialize
    @temperature = nil
  end

  def set_temparature
  end

  def drive
  end
end
cooling.rb
class Cooling < TemperatureControl
  def set_temparature
   @temperature = 28 # 室温を28度にセット
  end

  def drive
    # 設定温度にしたがって冷房運転を行う
  end
end
heating.rb
class Heating < TemperatureControl
  def set_temparature
   @temperature = 20 # 室温を20度にセット
  end

  def drive
    # 設定温度にしたがって暖房運転を行う
  end
end
eco_mode.rb
class EcoMode < TemperatureControl
  def drive
    # エコモードでの運転を行う
  end
end

クライアントコード

# 暑い!
remote_controller = RemoteController.new(Cooling.new)
remote_controller.drive
# 寒い!
remote_controller.set_drive_mode(Heating.new)
remote_controller.drive

メリット

  • 状態毎に振る舞いを分割し、新しい状態や遷移の追加がサブクラスの定義によって簡単に行える
  • 複数の状態に対して別々のオブジェクトを用意することで、状態の遷移を明確に表現できる
  • ConcreteStateオブジェクトをContextオブジェクトをまたいで共有することでメモリを節約できる

まとめ

オブジェクト本体と、その状態、振る舞いを表すオブジェクトを別に用意することで、条件分岐をへらし、新しい状態、振る舞いの追加を容易にできるパターン

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2