gofのデザインパターン stateパターン編
TRANSCRIPT
GoFのデザインパターン
Stateパターン編
2013/03/01(金)伊藤歩
本日のアジェンダ
・デザインパターンとは・Stateパターンの具体例
・Stateパターンのメリット
・デザインパターンの注意点
デザインパターンとは
過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。
wikipediaより
過去のソフトウェア設計者
過去のソフトウェア設計者
Gang of Four(ギャング・オブ・フォー、四人組)
Stateパターンの具体例サンプル
PLAY、STOP、PAUSEという状態がある
各状態で特定のコマンドを実行した時、違う挙動をするプログラムを作成する。
// コマンドqを受け取った場合
if (s.equals("q")) {if (mState == STATE_PLAY) {
System.out.println("STATE_PLAY:q");} else if (mState == STATE_STOP) {
System.out.println("STATE_STO::q");} else if (mState == STATE_PAUSE) {
System.out.println("STATE_PAUSE:q");}
}
if文で分岐させると・・・
// コマンドwを受け取った場合
if (s.equals("w")) {if (mState == STATE_PLAY) {
System.out.println("STATE_PLAY:w");} else if (mState == STATE_STOP) {
System.out.println("STATE_STOP:w");} else if (mState == STATE_PAUSE) {
System.out.println("STATE_PAUSE:w");}
}
if文で分岐させると・・・
// コマンドeを受け取った場合
if (s.equals("e")) {if (mState == STATE_PLAY) {
System.out.println("STATE_PLAY:e");} else if (mState == STATE_STOP) {
System.out.println("STATE_STOP:e");} else if (mState == STATE_PAUSE) {
System.out.println("STATE_PAUSE:e");}
}
if文で分岐させると・・・
さぁ野郎ども、
仕様追加のお時間だ!
さぁ野郎ども、
仕様追加のお時間だ!
コマンド”r”も追加な。※全部の状態で。
// コマンドrを受け取った場合
if (s.equals("r")) {if (mState == STATE_PLAY) {
System.out.println("STATE_PLAY:r");} else if (mState == STATE_STOP) {
System.out.println("STATE_STOP:r");} else if (mState == STATE_PAUSE) {
System.out.println("STATE_PAUSE:r");}
}
そしてこうなる
喜べ野郎ども、
また仕様追加だ!!!
喜べ野郎ども、
また仕様追加だ!!!
状態RECを追加な!※全部のコマンドで
喜べ野郎ども、
また仕様追加だ!!!
状態RECを追加な!※全部のコマンドで
状態×コマンド分の分岐が発生・・・
if文地獄の幕開けである。
そんなときにStateパターン
状態をクラスとして設計。
状態をクラスとして設計。
オブジェクトの状態に応じて、挙動を変える場合に有効。
そんなときにStateパターン
Stateパターンのクラス図
public interface State {void func_q();void func_w();void func_e();void func_r();
}
状態に応じたInterfaceを用意
public class PlayState implements State {public void func_q(){
System.out.println("STATE_PLAY:q");}public void func_w() {
System.out.println("STATE_PLAY:w");}public void func_e() {
System.out.println("STATE_PLAY:e");}public void func_r() {
System.out.println("STATE_PLAY:r");}
}
Interfaceを実装する状態クラス作成
StopやPauseも同様に、StateのInterfaceを実装します。
State state = null;if (n == STATE_PLAY) {
state = new PlayState();} else if (n == STATE_STOP) {
state = new StopState();} else if (n == STATE_PAUSE) {
state = new PauseState();}
状態によって、
オブジェクトを切り替える
// コマンドに応じて処理を実行
if (s.equals("q")) {state.func_q();
}if (s.equals("w")) {
state.func_w();}if (s.equals("e")) {
state.func_e();}
あとはメソッドを呼ぶだけ
Stateパターンのメリット
・コマンドや状態の追加で既存に影響ない。
・処理の修正は各Stateクラスで閉じる。
・コードの見通しが良くなる。
影響範囲が少ないので、デバッグ工数が削減可能。
保守性の向上。
デザインパターンの注意点
無理に導入しない。
Stateパターン使う俺カッコイイ(・∀・)みたいなノリで、使うのはNG。
あくまでオブジェクトの状態に応じて、挙動を変える場合に有効。