具有存储库模式的Laravel中的SOLID原则

Ari*_*que 7 oop design-patterns dry solid-principles laravel

在维护SOLID原则的同时,我对使用Controller with Repository Pattern感到困惑.考虑一下,我有两种类型的报价

  1. 商业报价
  2. 私人报价

并且未来很有可能出现新类型的报价.每个报价都有不同的字段,业务逻辑,但它们共享许多常用功能.所以我创建了一个QuotationInterface

报价界面

interface QuotationInterface
{   
    public function save(array $data);

}
Run Code Online (Sandbox Code Playgroud)

实现接口的报价类

class CommercialQuotation implements QuotationInterface
{   
    public function(array $data)
    {
        // save commercial quotation
    }
}

class PrivateQuotation implements QuotationInterface
{   
    public function(array $data)
    {
    // save Private quotation
    }
}
Run Code Online (Sandbox Code Playgroud)

报价库

class QuotationRepository 
{
    public function save(array $data, QuotationInterface $quotation)
    {
        $quotation->save($data);
    }
}
Run Code Online (Sandbox Code Playgroud)

QotationController

public function store(Resource $resource)
{

    $inputs = $resource->all();

    /**
    *  Clearly here Open/Close Principle is broken
    */

    if ($inputs['type'] == 'private'){
        $quotation = new PrivateQuotation;;
    }
    else if($inputs['type'] == 'commercial'){
        $quotation = new CommercialQuotation;
    }

    $this->repo->save($inputs, $quotation);
}
Run Code Online (Sandbox Code Playgroud)

在我的QuotationController中,它显然违反了开/关原则..

为每种类型的报价创建一个控制器(一天可能是10+,谁知道?)是一个好主意,以避免OCP违规或我的设计是错的?欢迎任何建议,设计变更提示,资源.

注意:除了仅保存之外,我的报价控制器还有许多其他功能.

Mop*_*ppo 5

如果你按照你展示的方式前进,我建议你使用一个控制器作为你的报价,并使用工厂设计模式来创建你的$quotation对象

例如,使用这样的简单工厂:

//FACTORY CLASS
abstract class QuotationFactory
{
    /** return QuotationInterface */
    public static function createQuotation($type)
    {
        switch($type)
        {
            CASE "private":
                return new PrivateQuotation();
            break;

            CASE "commercial":
                return new CommercialQuotation();
            break;    
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用控制器方法中的工厂:

//YOUR CONTROLLER'S METHOD
public function store(Resource $resource)
{   
    $inputs = $resource->all();

    //delegate objects creation to factory class
    $quotation = QuotationFactory::createQuotation( $inputs['type'] );

    $this->repo->save($inputs, $quotation);
}
Run Code Online (Sandbox Code Playgroud)

这样你就不会违反控制器中的开/关原则,因为当你添加引号时,你只需要修改工厂的方法(将例子添加到switch语句中),它将返回一个QuotationFactory对象在需要的地方.

这也将使代码保持DRYSOLID,因为您不必重复if/else语句来在控制器的方法中创建对象,因为您将对象创建的责任委派给特定的工厂类

由于正确地指出在下面的意见'mount,简单工厂将帮助你避免开/闭原则在你的控制器,但可以洁具是,从更广泛的角度,简单工厂本身固有违反了OCP,因为它使用开关盒.

无论如何,从我所看到的应用程序来看,Simple工厂可能是一个很好的解决方案,因为您主要关注的是在变量类型的许多地方实例中构建.因此,使用Simple工具,您可以"隐藏"创建对象到工厂的过程,并在控制器中获取所需的实例.所以你只是在交换机机箱内的工厂内部违反了OCP,但我认为这可能是一个可靠的权衡