laravel 策略模式、工厂模式使用案例
laravel 策略模式、工厂模式使用案例
在 Laravel 中使用设计模式来对接多个物流服务商(如菜鸟、顺丰、极兔),可以使用 策略模式 或 工厂模式 来实现动态调用不同物流接口的功能。下面的示例展示了如何使用策略模式来实现这个需求,通过一个父类,多个子类来处理不同的物流服务商,并根据单号选择对应的物流服务商。
步骤
- 定义物流接口(父类):定义物流接口,所有物流服务商都必须实现该接口。
- 定义各个物流服务商的子类:每个物流服务商继承父类并实现特定的物流接口逻辑。
- 编写服务工厂类:根据传入的物流单号选择合适的物流服务商类。
- 使用依赖注入调用相应物流服务商。
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
使用极兔物流
总结
通过使用策略模式(结合工厂模式),你可以轻松对接多个物流服务商,并根据物流单号选择合适的服务。