StoreパターンとStateパターンって、
どう違うの?
Storeパターンを学習して思ったことは、「Stateパターンとどう違うの?」ということでした。
そこで今回Stateパターンに興味を持ち学習することにしました
参考書籍ですが、「Java言語で学ぶ デザインパターン入門」です
まずはソースコードをダウンロードしました。
おおおおおお!!
各デザインパターンのディレクトリ見れて良きです
やはり書籍もいいですが、コードエディター上で実際のコードを見るのが一番理解に繋がる気がします。
コードジャンプと検索を繰り返して、構造を理解していきます。
そもそもなぜStateパターンが誕生したのか?
これ面白いのが、時間や季節など“モノ“ではない“状態”もオブジェクト思考だとclass化しないといけないってことです。
昼と夜という“状況”を定義するとして、それを実現するために太陽や地球のclassを作るのもちょっと違いますよね
確かにそうだ…。
太陽とか壮大すぎ….。
オブジェクト思考は素晴らしいですが、“モノ”ではなくて“状況・状態”でしか表現できないものもあるよね。
じゃあ、状況・状態を表現するには、どうすればよいでしょうか?
その解決策として、Stateパターンが誕生したということです。
なるほど!!これは面白そうだ
なぜStateパターンがいいのか?そのメリット
Stateパターンを使う、使わないでどういった違いが生まれるのか?
何回もif文を書くか、1回のif文で完結させるか。
上記の違いが生まれます。
結論をいうと、下記になります。
- Stateパターンを使わない場合:if文がたくさん必要。
- Stateパターンを使う場合:1回のif文で完結する
具体的に違いをみてみましょう!
擬似コーディングで比較する
Stateパターンを使わない場合,if文が多くなる。
<?php
class お店
{
/**
* お店が空いているか尋ねる。
*
* @return string
*/
public function isOpened(): string
{
if(昼) {
echo "営業中です";
} elseif(夜) {
echo "営業時間外です";
}
}
/**
* 店員に尋ねる
*
* @return string
*/
public function call(): string
{
if(昼) {
echo "はい、なんでしょうか?";
} elseif(夜) {
echo "zzzz。";
}
}
}
Stateパターンを使う場合、if文が1回で済む
<?php
class お店
{
private State $state;
/**
* お店の状況を確認する。
*
* @return void
*/
public function checkState()
{
// このif文で完結
if (昼) {
$this->state = 開店ステータスクラス;
} elseif (夜) {
$this->state = 閉店ステータスクラス;
}
}
/**
* お店が空いているか尋ねる。
*
* @return string
*/
public function isOpened(): string
{
$this->state->isOpened(); // if文が不要
}
/**
* 店員に尋ねる
*
* @return string
*/
public function call(): string
{
$this->state->call(); // if文が不要
}
}
こんな感じになります。
擬似コーディングじゃない…。
擬似コード書くつもりが、ちょっとPHP混じってしまいました笑
Stateパターンを使わない場合、メソッドごとにif文が必要になります。
Stateパターンを使うと、Stateの切り替え時のみif文を使います。
if文1回で済むとか最高じゃん
そうですよね。
if文が1回で済むことで、コードがシンプルになりますし、非常に可読性も高まります。
if文でごちゃつかないのは魅力の一つだと思います。
これ考えた人めっちゃ賢いですよね。すごくないですか?
理解を深める
さて、Stateパターンの魅力を理解したところで、クラス設計の理解を深めましょう。
先ほどの擬似コーディングはあくまで魅力を伝えるためのものです。
実際にはクラス分けをして、役割を分担させます。
じゃあ、どうやってClassを分けようか?
という疑問が生まれるはずです。
そこで、Stateパターンのクラス設計を理解していきましょう!
まず状態を表現するクラスの役割ですが、大きくわけると2つあります。
- 対象の状況
- 状態
図解で理解しよう
図解でお伝えしていきましょう。
まずは先ほどお伝えした二つのクラスです。
さらに状態は複数あるので、具体的な状態を追加します。
この3つが状態を表現するために必須なクラスです。
ごめん、Contextがわからないです。
そうですよね。Contextはちょっとわかりづらいですよね。
ですが、人で比喩するとわかりやすいですよ
人間の場合、感情の状態もあれば、体調の状態もあります。
このように状態といってもグループ分けできますよね。
どの対象についての状態なのか?これを表現するのかContextです。
Contextでメソッドのふるまいを持たせて、Stateの状態によって処理内容が変わる仕組みです。
超わかりやすい!!
それでは抽象的な概念がわかったところで、よりプログラムに落とし込みます。
EmotionsContextの処理を実行 → 現在の状態であるStateの実装クラスを1つの値を取得・処理を実行
といった関係ですね
これで同じふるまいでも、状態によって変化する面白いプログラムが作れますね
これらを理解した上で書籍を読んでみると、理解度がぐん!と上がるのでおすすめです。
終わりに
ということで、今回stateパターンを学習しました。
Storeパターンは状態を管理するオブジェクトをimportして、値を更新してました。
Stateパターンはさらに詳しいクラス設計で、状態を管理するStateの他にふるまいをもつContextクラスをもつことで、無駄なif文なく処理をつくることができる。
こういう認識です。
書籍の内容をまるごと使うと、ただのコピペですし、著作権的にもよろしくないので、自分なりの理解で書いてみました。
間違い等があれば、ぜひぜひ教えてください。
コメント