LARAVEL:如何使用Open Close原理的SOLID原则?

问题描述 投票:5回答:1

我有一个以下结构来使用Open Close 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
    }
}

调节器

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是否正确?使用上面的代码我可以告诉控制器我可以使用PaymentService类来实现。

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

如果以后我想以不同的方式付款,例如通过发票付款然后我可以创建新的控制器,在新的类中编写新的实现,例如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);

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

如果我以错误的方式这样做,请告诉我。

php laravel solid-principles open-closed-principle
1个回答
5
投票

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

假设你有一个接口:FooInterface

你有两个具体的实现:Good Food和Badoo

为了向控制器(或其他类)注入不同的实现,你必须告诉它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();
      });

控制器应该是:

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原则。

© www.soinside.com 2019 - 2024. All rights reserved.