PHP策略模式在業務的實踐總結

CodeUndefined發表於2021-01-21

【大話設計模式】– 策略者模式(Strategy):它定義了演算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變法,不會影響到使用演算法的客戶。

策略模式的核心就是遮蔽內部策略演算法,內部的演算法是可以隨時替換,對外部是沒有感知的。若新增或修改內部的演算法,只需要修改或者擴充套件相應的策略類,客戶端的程式碼無需改動,符合設計模式中一個重要的原則:開閉原則。

一. 業務需求背景

1.需求目的:
使用者可以進行對某種配置進行預約,到達配置的預約時間點,根據Redis佇列的預約號執行預約,不同型別的配置預約操作邏輯完全不同。
2.流程圖:

二. 使用策略模式的緣由

此業務由於是要支援不同配置的預約,以及後期可能會有很多種型別的配置,而且不同型別的配置又完成不同,如果直接編碼,後期的擴充套件性以及維護性會比較麻煩。
1.正常程式碼實現:

<?php
    public function makeReservation($mainkey){
        $type = getReservationTypeByMainkey($mainkey);
        switch($type):{
            case 'A':
            $this->reservationAConfig($mainkey);
            break;
            case 'B':
            $this->reservationBConfig($mainkey);
            break;
            .....
        }
    }

    private function reservationAConfig($mainkey){
        //這裡進行A配置的預約邏輯操作
    }

    private function reservationBConfig($mainkey){
        //這裡進行B配置的預約邏輯操作
    }

    private function getReservationTypeByMainkey($mainkey){
        //根據預約號獲取預約配置的型別
    }

這樣子的實現也是可以滿足業務需求,程式碼的可讀性也還好。但是會有一個問題,這種預約的配置種類會很多,會導致switch的語句會越來越多,也可能會修改一些預約配置邏輯。這樣子的話就需要修改原來的程式碼,對於程式碼質量來說,這並不是一種好的現象。

2.策略模式實現

<?php

interface ReservationStrategy
{
    //執行預約配置邏輯操作
    public function makeReservation();
}

//策略處理類
class ReservationHandler
{
    private $strategy = null;
    public function __construct(ReservationStrategy $strategy){
        $this->$strategy = $strategy;
    }

    //封裝了策略執行的邏輯,所有執行的預約配置統一呼叫這個方法
    public function makeReservation(){
        $this->$strategy->makeReservation();
    }

}

//A配置的具體策略類
class AReservationStrategy implements ReservationStrategy
{
    public function makeReservation(){
        //這裡執行A配置的邏輯操作
    ;
}

class ReservationFacaory
{
    public static function getReservationInstance($mainkey){
        //這裡可以根據預約號做具體邏輯生成策略物件
    }
}
//預約控制器程式碼
class ReservationController
{
    public function makeReservation($mainkey){
        //根據工廠物件建立預約策略例項
        $reservation = ReservationFacaory::getReservationInstance($mainkey);
        //傳入例項給策略處理類
        $handler = new ReservationHandler($reservation);
        //執行預約策略
        $handler->makeReservation();
    }

}

以上程式碼使用了工廠模式以及策略模式的結合,其中ReservationHandler類作為處理上下文的類,通過依賴注入相應的策略類,直接呼叫makeReservation方法。在客戶端程式碼只需要呼叫此方法即可,即使後期預約邏輯也無需改動客戶端的程式碼。在此業務需求,因為需求並不是很大,所以工廠類只是簡單實現。如果想要更完善,工廠類根據反射機制以及約定好的類名動態生成例項,這樣後期如果擴充套件型別,只需要實現相應的介面即可,無需改動其他程式碼,很方便擴充套件。

總結

實踐才能出真知。以前看大話設計模式這本書,總覺得自己看了好多遍但是還是雲裡霧裡的,不知道為什麼需要這種程式碼結構。但是通過一個小需求設計這麼一個結構,我很快就能get到這種結構帶來的好處。雖然在這個業務上,這種結構的優勢並沒有特別的明顯,甚至可能有點增加程式碼量,但是我相信在後期擴充套件以及維護方便是有很大的好處的。記錄這篇文章,主要是想要記錄自己的思考方式以及學習體會,如果有一些不太對的地方歡迎大家指正,一起進步!!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章