萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 狀態模式實作:坦克攻城/通常模式切換

狀態模式:將狀態相關行為封裝進獨立類別

狀態模式 讓物件在內部狀態改變時改變行為,物件看起來像改變了類別。適用於:有限狀態機 (FSM)、遊戲角色狀態、訂單流程、TCP 連線狀態、文檔審核流程等。

核心結構

  • State (狀態介面):定義狀態相關操作 (如 attack())。
  • ConcreteState (具體狀態):實作特定狀態下的行為。
  • Context (環境/主體):持有當前狀態參考,委派行為給狀態物件,負責狀態切換邏輯。

坦克模式切換範例

<?php
// 狀態介面
interface TankState {
    public function attack(Tank $tank): void;
    public function move(Tank $tank, int $x, int $y): void;
    public function getName(): string;
}

// 通常模式 (可移動、射程短、傷害低)
class TankMode implements TankState {
    public function attack(Tank $tank): void {
        echo "🚗 坦克[通常模式] 發射穿甲彈 → 傷害 30
"; } public function move(Tank $tank, int $x, int $y): void { $tank->x = $x; $tank->y = $y; echo "🚗 移動至 ({$x}, {$y})
"; } public function getName(): string { return '通常模式'; } } // 攻城模式 (不可動、射程遠、傷害高、範圍傷害) class SiegeMode implements TankState { public function attack(Tank $tank): void { echo "💥 坦克[攻城模式] 發射電漿砲 → 傷害 70 (範圍 1.5)
"; } public function move(Tank $tank, int $x, int $y): void { echo "⛔ 攻城模式無法移動!需先解除攻城
"; } public function getName(): string { return '攻城模式'; } } // 環境類別:坦克 class Tank { public int $x = 0; public int $y = 0; public int $hp = 150; private TankState $state; public function __construct() { $this->state = new TankMode(); // 初始狀態 } // 狀態切換 (可加入冷卻、動畫等邏輯) public function setState(TankState $state): void { echo "🔄 狀態切換: {$this->state->getName()} → {$state->getName()}
"; $this->state = $state; } // 委派給當前狀態 public function attack(): void { $this->state->attack($this); } public function move(int $x, int $y): void { $this->state->move($this, $x, $y); } public function getStateName(): string { return $this->state->getName(); } } // 使用示範 $tank = new Tank(); echo "初始: {$tank->getStateName()}
"; $tank->attack(); // 通常模式攻擊 $tank->move(100, 200); // 移動 $tank->setState(new SiegeMode()); // 部署攻城 $tank->attack(); // 攻城模式攻擊 $tank->move(150, 200); // 嘗試移動 (失敗) $tank->setState(new TankMode()); // 解除攻城 $tank->move(150, 250); // 可移動 $tank->attack(); ?>

進階:狀態切換邏輯內聚到狀態類別

<?php
interface State {
    public function handle(Context $ctx, string $event): void;
}

class Context {
    private State $state;
    public function __construct(State $initial) { $this->state = $initial; }
    public function setState(State $s): void { $this->state = $s; }
    public function request(string $event): void { $this->state->handle($this, $event); }
}

class StateA implements State {
    public function handle(Context $ctx, string $event): void {
        match ($event) {
            'go_b' => $ctx->setState(new StateB()),
            'go_c' => $ctx->setState(new StateC()),
            default => echo "StateA 忽略事件: {$event}
", }; } } class StateB implements State { public function handle(Context $ctx, string $event): void { if ($event === 'back') $ctx->setState(new StateA()); } } class StateC implements State { public function handle(Context $ctx, string $event): void { if ($event === 'back') $ctx->setState(new StateA()); } } $ctx = new Context(new StateA()); $ctx->request('go_b'); // 切換到 B $ctx->request('go_c'); // B 忽略 $ctx->request('back'); // 回到 A ?>

狀態模式 vs 策略模式 vs 型別檢查

維度狀態模式策略模式if/else 型別檢查
狀態切換內建 (Context 委派)外部注入手動分支
狀態專屬資料封裝在 State 類封裝在 Strategy 類分散在 Context
新增狀態新增 State 類 (OCP)新增 Strategy 類修改分支 (違反 OCP)
適用場景物件行為隨狀態大幅改變、狀態間有轉換規則演算法可互換、客戶端選擇簡單、固定、少量分支

PHP 8.1+ Enum 實作狀態機 (現代替代方案)

<?php
enum OrderStatus: string {
    case Pending   = 'pending';
    case Paid      = 'paid';
    case Shipped   = 'shipped';
    case Delivered = 'delivered';
    case Cancelled = 'cancelled';
    
    public function canTransitionTo(self $next): bool {
        return match($this) {
            self::Pending   => in_array($next, [self::Paid, self::Cancelled]),
            self::Paid      => in_array($next, [self::Shipped, self::Cancelled]),
            self::Shipped   => in_array($next, [self::Delivered]),
            self::Delivered => false,
            self::Cancelled => false,
        };
    }
}

$order = OrderStatus::Pending;
$order = $order->canTransitionTo(OrderStatus::Paid) ? OrderStatus::Paid : $order;
// 型別安全、自動完成、IDE 支援、不可變
?>

狀態模式將「狀態判斷分支」轉化為「多型派發」,新增狀態零修改既有代碼,讓複雜狀態機保持清晰可維護。

copyright © 萬盛學電腦網 all rights reserved