使用解析器简化 Laravel 中的服务选择
发布: (2025年12月27日 GMT+8 23:34)
3 min read
原文: Dev.to
Source: Dev.to
问题:过多的 if‑else 条件
if ($paymentType === 'stripe') {
$service = new StripePaymentService();
} elseif ($paymentType === 'paypal') {
$service = new PaypalPaymentService();
} else {
throw new Exception('Invalid payment type');
}
$service->charge($data);
这种做法有什么问题?
- 业务逻辑与具体实现紧密耦合。
- 添加新的支付网关需要修改已有代码。
- 难以测试和维护。
- 违反了开放/封闭原则。
代码可以工作,但扩展性不佳。
什么是 Resolver?
Resolver 是一个类,负责根据运行时数据决定应使用哪种服务实现。简单来说,Resolver 为你返回正确的服务类,使业务逻辑保持简洁。
实际案例:支付服务 Resolver
步骤 1:创建通用接口
$this->stripePaymentService,
'paypal' => $this->paypalPaymentService,
default => throw new InvalidArgumentException('Unsupported payment type'),
};
}
}
为什么使用构造函数注入?
- 使依赖关系明确,易于理解。
- 提升单元测试的可行性(服务可以被模拟)。
- 让 Resolver 专注于选择逻辑。
- 利用 Laravel 的依赖注入容器。
Note: 你也可以在 Resolver 中使用
app()来解析服务,但一般更推荐使用构造函数注入,以获得更清晰的架构和更好的可测试性。
步骤 4:在业务逻辑中使用 Resolver
get('payment_type');
$service = $resolver->resolve($paymentType);
$service->charge($request->all());
return response()->json([
'message' => 'Payment processed successfully',
]);
}
}
✨ 简洁、可读且易于扩展。
添加新服务很容易
想以后添加 Razorpay 吗?
- 创建实现
PaymentServiceInterface的RazorpayPaymentService。 - 更新 Resolver:
'razorpay' => $this->razorpayPaymentService,
控制器或其他业务逻辑无需做任何更改。
使用 Resolver 的好处
- 代码更简洁、更易读。
- 轻松添加新服务。
- 遵循 SOLID 原则。
- 服务选择逻辑集中管理。
- 单元测试简单。
额外收获:让 Resolver 更灵活
基于配置的映射
// config/payment.php
return [
'stripe' => StripePaymentService::class,
'paypal' => PaypalPaymentService::class,
];
使用配置的 Resolver
<?php
class PaymentServiceResolver
{
public function resolve(string $type): PaymentServiceInterface
{
$service = config("payment.$type");
if (! $service) {
throw new InvalidArgumentException('Unsupported payment type');
}
return app($service);
}
}
这种方式使系统更加可配置。
最终思考
Resolver 是一种简单却强大的模式,用于在 Laravel 中管理多个服务实现。它帮助你:
- 避免混乱的条件判断。
- 保持业务逻辑清晰。
- 构建能够优雅扩展的系统。
如果你在项目中使用多个 API、支付网关或供应商,Resolver 可以显著提升代码质量。