策略模式在PHP業務程式碼的實踐

小菜雞Lee發表於2021-03-14

【大話設計模式】-- 策略者模式(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到這種結構帶來的好處。雖然在這個業務上,這種結構的優勢並沒有特別的明顯,甚至可能有點增加程式碼量,但是我相信在後期擴充套件以及維護方便是有很大的好處的。記錄這篇文章,主要是想要記錄自己的思考方式以及學習體會,如果有一些不太對的地方歡迎大家指正,一起進步!!

相關文章