1. 程式人生 > 實用技巧 >php 23種設計模型 - 狀態模式

php 23種設計模型 - 狀態模式

狀態模式

狀態模式當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類。狀態模式主要解決的是當控制一個物件狀態的條件表示式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判斷邏輯簡化。

角色:
上下文環境(Work):它定義了客戶程式需要的介面並維護一個具體狀態角色的例項,將與狀態相關的操作委託給當前的具體物件來處理。
抽象狀態(State):定義一個介面以封裝使用上下文環境的的一個特定狀態相關的行為。
具體狀態(AmState):實現抽象狀態定義的介面。

優點:1、封裝了轉換規則。 2、列舉可能的狀態,在列舉狀態之前需要確定狀態種類。 3、將所有與某個狀態有關的行為放到一個類中,並且可以方便地增加新的狀態,只需要改變物件狀態即可改變物件的行為。 4、允許狀態轉換邏輯與狀態物件合成一體,而不是某一個巨大的條件語句塊。 5、可以讓多個環境物件共享一個狀態物件,從而減少系統中物件的個數。

缺點:1、狀態模式的使用必然會增加系統類和物件的個數。 2、狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和程式碼的混亂。 3、狀態模式對"開閉原則"的支援並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的原始碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的原始碼。

使用場景:1、行為隨狀態改變而改變的場景。 2、條件、分支語句的代替者。

interface State { // 抽象狀態角色
    public function handle(Context $context); // 方法示例
}

class ConcreteStateA implements State { // 具體狀態角色A
    private static $_instance = null;
    private function __construct() {}
    public static function getInstance() { // 靜態工廠方法,返還此類的唯一例項
        if (is_null(self::$_instance)) {
            self::$_instance = new ConcreteStateA();
        }
        return self::$_instance;
    }

    public function handle(Context $context) {
        echo 'concrete_a'."<br>";
        $context->setState(ConcreteStateB::getInstance());
    }

}

class ConcreteStateB implements State { // 具體狀態角色B
    private static $_instance = null;
    private function __construct() {}
    public static function getInstance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new ConcreteStateB();
        }
        return self::$_instance;
    }

    public function handle(Context $context) {
        echo 'concrete_b'."<br>";
        $context->setState(ConcreteStateA::getInstance());
    }
}

class Context { // 環境角色 
    private $_state;
    public function __construct() { // 預設為stateA
        $this->_state = ConcreteStateA::getInstance();
    }
    public function setState(State $state) {
        $this->_state = $state;
    }
    public function request() {
        $this->_state->handle($this);
    }
}

// client
$context = new Context();
$context->request();
$context->request();
$context->request();
$context->request();
/* 輸出:
concrete_a
concrete_b
concrete_a
concrete_b */

  

23種模式總覽 :https://www.cnblogs.com/houss/p/11121584.html