狀態模式屬於行為型模式,其意圖是允許一個對象在內部狀態改變時改變其行為,彷彿該對象修改了其類別。關鍵在於引入抽象狀態類別,將各具體狀態的行為封裝於獨立類別中,Context 持有當前狀態引用並委派請求。
一個 TCPConnection 物件可能處於 Established、Listening、Closed 等狀態。收到 Open 請求時,若當前狀態為 Closed 則建立連線;若為 Established 則忽略或報錯。每種狀態對應不同行為,狀態轉換由狀態類別內部控制。
<?php
/**
* 狀態模式
* 允許一個對象在其內部狀態改變時改變它的行為
*/
interface State {
public function handle($context);
public function display();
}
class Context {
private $_state = null;
public function __construct($state) {
$this->setState($state);
}
public function setState($state) {
$this->_state = $state;
}
public function request() {
$this->_state->display();
$this->_state->handle($this);
}
}
class StateA implements State {
public function handle($context) {
$context->setState(new StateB());
}
public function display() {
echo "state A<br/>";
}
}
class StateB implements State {
public function handle($context) {
$context->setState(new StateC());
}
public function display() {
echo "state B<br/>";
}
}
class StateC implements State {
public function handle($context) {
$context->setState(new StateA());
}
public function display() {
echo "state C<br/>";
}
}
// 狀態循環:A -> B -> C -> A ...
$objContext = new Context(new StateB());
$objContext->request(); // state B -> 切換到 C
$objContext->request(); // state C -> 切換到 A
$objContext->request(); // state A -> 切換到 B
$objContext->request(); // state B -> 切換到 C
$objContext->request(); // state C -> 切換到 A
?>
物件行為隨狀態頻繁變化、狀態轉換邏輯複雜、需避免龐大條件判斷的場景(如訂單狀態流程、遊戲角色狀態、工作流引擎)。