php - LARAVEL:如何使用SOLID原则的Open Close Principle?

标签 php laravel solid-principles open-closed-principle

我有以下结构来使用打开关闭原则

class Payment{ 

    //this is not a model class
    // according to OC principle this class should not focus on the implementation

    private $paymentInterface;

    public function __construct(PaymentInterface $paymentInterface)
    {
        $this->paymentInterface = $paymentInterface;
    }


    //so store method does not know which implementation it will get
    public function store($request,$id)
    {
        return $this->paymentInterface->store($request,$id);
    }

}

界面

interface PaymentInterface{
    public function store($request,$id = null);
}

包含实现的支付服务类

class PaymentService implements PaymentInterface{
    public function store($request,$id = null){
        //payment store logic is here
    }
}

Controller

class PaymentsController extends Controller{

    protected $payment;

    public function __construct()
    {
        $this->payment = new Payment(new PaymentService);
    }

    public function storePayment(PaymentRequest $request, $id)
    {
        try {
             $response = $this->payment->store($request,$id);
             return redirect()->route($this->route.'.index')->with($response['status'],$response['message']);
        } catch (\Exception $e) {
            return $this->vendorDashboard($e);
        }
    }
}

我的问题是: 使用 Open-Close-Principle 是否正确? 使用上面的代码我可以告诉 Controller 我可以使用 PaymentService 类来实现。

$payment = new Payment(new PaymentService);
return $payment->store($request,$id);

如果稍后我想以不同的方式付款,例如通过发票付款然后我可以创建新的 Controller ,在新类中编写新的实现,例如InvoicePaymentService 并告诉 Payment 类使用 InvoicePaymentService 作为实现

$payment = new Payment(new InvoicePaymentService);
return $payment->store($request,$id);

$payment = new Payment(new PayPalPaymentService);
return $payment->store($request,$id);

$payment = new Payment(new AliPayPaymentService);
return $payment->store($request,$id);

我知道我可以通过服务提供商将接口(interface)与类绑定(bind),但如果我想实现不同的支付实现,那么我将无法更改类,对吧?

如果我做错了,请告诉我。

最佳答案

这就是服务容器的含义。你应该使用 contextual binding

假设你有一个接口(interface):FooInterface

您有两个具体实现:GoodFooBadFoo

为了向 Controller (或其他类)注入(inject)不同的实现你必须告诉 laravel。

$this->app->when(GoodController::class)
      ->needs(FooInterface::class)
      ->give(function () {
            return new GoodFoo();
      });


$this->app->when(BadController::class)
      ->needs(FooInterface::class)
      ->give(function () {
            return new BadFoo();
      });

Controller 应该是:

class GoodController extends Controller
{
    protected $foo;

    public function __construct(FooInterface $foo)
    {
        $this->foo = $foo;
    }
}

class BadController extends Controller
{
    protected $foo;

    public function __construct(FooInterface $foo)
    {
        $this->foo = $foo;
    }
}

请注意,大多数时候 laravel 提倡糟糕的软件设计原则,并且很难在 laravel 中实践 SOLID 原则。

关于php - LARAVEL:如何使用SOLID原则的Open Close Principle?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55040713/

相关文章:

php - 通过合并PHP和MySql覆盖的条件是否有利于减少DB调用次数

php - 从多表 SQL 中获取值

使用 Laravel 通过 SSL 连接 MySQL

php - laravel session 购物车 - 如果产品已经存在,如何增加数量

php - 拉维尔 5 : Controller Testing - PHPUnit returns green

wpf - 如何在 MVVM 中构建 ViewModel 不违反单一职责原则?

oop - 什么时候可以依赖具体类?

php - 使用 MongoDate 与 UTCDateTime 进行查询

c# - 将不同的实现注入(inject)同一接口(interface),然后在正确的项目/程序集中选择正确的实现

php 未登录 mysql 或响应