【大话设计模式】– 策略者模式(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到这种结构带来的好处。虽然在这个业务上,这种结构的优势并没有特别的明显,甚至可能有点增加代码量,但是我相信在后期扩展以及维护方便是有很大的好处的。记录这篇文章,主要是想要记录自己的思考方式以及学习体会,如果有一些不太对的地方欢迎大家指正,一起进步!!

版权声明:本文为leeee原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/leeee/p/14532941.html