[英]Select interface implementation according to parameter
根据传递的参数选择接口实现的正确方法是什么?
让我们有以下代码:
interface PaymentProcessor {
public function process(Order $order): void;
}
class CardPayment implements PaymentProcessor {}
class BankTransfer implements PaymentProcessor {}
class OrderService {
public function __construct( // Load payment processors from DI
private CardPayment $cardPayment,
private BankTransfer $bankTransfer,
) {}
// This is what is not clear to me
private function getPaymentProcessor(string $paymentMethod): PaymentProcessor
{
return match ($paymentMethod) {
'card' => $this->cardPayment,
'bank' => $this->bankTransfer,
}
}
public function payOrder(Order $order): void
{
$processor = $this->getPaymentProcessor($order->getPaymentMethod());
$processor->process($order);
}
}
我不清楚的是如何通过付款方式名称获取 PaymentProcessor。
我会使用上面的代码,可能提取到一些“工厂”。 但根据PHP - Using Interfaces, Strategy Pattern and Optional Method Parameters的回答,我可能打破了打开/关闭原则。 那么正确的方法应该是什么?
做到这一点的正确方法可能是策略模式和依赖注入的组合。
参考答案中发布的解决方案是正确的,但缺少一个重要的点 - 诀窍是所有映射都可以通过依赖注入完成。
所以你可以拥有
interface PaymentStrategy {
public function process(): void;
}
class CardPayment implements PaymentStrategy {
public function process(): void;
}
class BankTransfer implements PaymentStrategy {
public function process(): void;
}
class PaymentService {
private PaymentStrategy $strategy;
/** @var array<string, PaymentStrategy> $processors */
public function __construct(private array $processors) {
}
public function setStrategy(string $paymentMethod): void {
if (!array_key_exists($paymentMethod, $this->processors)) {
throw new \InvalidArgumentException('Processor not found');
}
$this->strategy = $this->processors[$paymentMethod];
}
public function process(): void {
$this->strategy->process();
}
}
因此,您需要做的就是说服您的 DI 容器为您提供所有 PaymentStrategy 实现。 理想情况下采用 paymentMethodName - 策略格式。 或者,您可以向接口和类添加一些函数,返回它的支付方式名称 - 然后运行 foreach - if - return。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.