laravel 策略模式、工厂模式使用案例

laravel 策略模式、工厂模式使用案例

在 Laravel 中使用设计模式来对接多个物流服务商(如菜鸟、顺丰、极兔),可以使用 策略模式工厂模式 来实现动态调用不同物流接口的功能。下面的示例展示了如何使用策略模式来实现这个需求,通过一个父类,多个子类来处理不同的物流服务商,并根据单号选择对应的物流服务商。

步骤

  1. 定义物流接口(父类):定义物流接口,所有物流服务商都必须实现该接口。
  2. 定义各个物流服务商的子类:每个物流服务商继承父类并实现特定的物流接口逻辑。
  3. 编写服务工厂类:根据传入的物流单号选择合适的物流服务商类。
  4. 使用依赖注入调用相应物流服务商

1. 定义物流接口

app/Services/Shipping/ShippingServiceInterface.php 中定义接口。


namespace App\Services\Shipping;

interface ShippingServiceInterface
{
    public function track($trackingNumber);
}

2. 实现各个物流服务商(子类)

app/Services/Shipping/ 目录下,为每个物流公司创建一个类。

菜鸟物流类


namespace App\Services\Shipping;

class CainiaoShippingService implements ShippingServiceInterface
{
    public function track($trackingNumber)
    {
        // 菜鸟物流的具体查询逻辑
        return "Tracking Cainiao package: " . $trackingNumber;
    }
}

顺丰物流类


namespace App\Services\Shipping;

class SFShippingService implements ShippingServiceInterface
{
    public function track($trackingNumber)
    {
        // 顺丰物流的具体查询逻辑
        return "Tracking SF package: " . $trackingNumber;
    }
}

极兔物流类


namespace App\Services\Shipping;

class JituShippingService implements ShippingServiceInterface
{
    public function track($trackingNumber)
    {
        // 极兔物流的具体查询逻辑
        return "Tracking Jitu package: " . $trackingNumber;
    }
}

3. 创建物流服务工厂类

app/Services/Shipping/ShippingServiceFactory.php 中创建一个工厂类,负责根据单号选择对应的物流服务商。


namespace App\Services\Shipping;

class ShippingServiceFactory
{
    public function getShippingService($trackingNumber)
    {
        // 根据 trackingNumber 判断使用哪个物流服务商
        if (strpos($trackingNumber, 'CN') === 0) {
            return new CainiaoShippingService();
        } elseif (strpos($trackingNumber, 'SF') === 0) {
            return new SFShippingService();
        } elseif (strpos($trackingNumber, 'JT') === 0) {
            return new JituShippingService();
        } else {
            throw new \Exception('No matching shipping service found.');
        }
    }
}

4. 在控制器中调用

app/Http/Controllers/ShippingController.php 中编写控制器,调用物流服务。


namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\Shipping\ShippingServiceFactory;

class ShippingController extends Controller
{
    protected $shippingFactory;

    public function __construct(ShippingServiceFactory $shippingFactory)
    {
        $this->shippingFactory = $shippingFactory;
    }

    public function trackPackage($trackingNumber)
    {
        try {
            // 根据单号选择对应的物流服务
            $shippingService = $this->shippingFactory->getShippingService($trackingNumber);
            $trackingInfo = $shippingService->track($trackingNumber);

            return response()->json([
                'status' => 'success',
                'data' => $trackingInfo
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 400);
        }
    }
}

5. 路由

routes/web.php 中添加路由:


use App\Http\Controllers\ShippingController;

Route::get('/track/{trackingNumber}', [ShippingController::class, 'trackPackage']);

6. 依赖注入配置(可选)

为了更方便使用 Laravel 的依赖注入机制,你可以在 AppServiceProvider 中将服务工厂类注册为单例。


namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\Shipping\ShippingServiceFactory;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(ShippingServiceFactory::class, function ($app) {
            return new ShippingServiceFactory();
        });
    }

    public function boot()
    {
        //
    }
}

使用

你可以通过访问 /track/{trackingNumber} 来测试。例如:

  • /track/CN123456 使用菜鸟物流
  • /track/SF123456 使用顺丰物流
  • /track/JT123456 使用极兔物流

总结

通过使用策略模式(结合工厂模式),你可以轻松对接多个物流服务商,并根据物流单号选择合适的服务。

posted @ 2024-09-10 17:30  pine007  阅读(65)  评论(0编辑  收藏  举报