PHP策略模式在业务的实践总结

【大话设计模式】– 策略者模式(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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!