oop - Laravel 中的 SOLID 原理与存储库模式

标签 oop laravel design-patterns dry solid-principles

在保持 SOLID 原则的同时,我对使用具有存储库模式的 Controller 有些困惑。考虑一下,我有两种类型的报价单

  • 商业报价
  • 私有(private)报价

  • 并且 future 很有可能出现新的报价类型。每个报价都有不同的领域、业务逻辑,但它们共享许多共同的功能。所以我创建了一个 QuotationInterface

    报价界面

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

    实现接口(interface)的引用类

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

    报价库

    class QuotationRepository 
    {
        public function save(array $data, QuotationInterface $quotation)
        {
            $quotation->save($data);
        }
    }
    

    报价 Controller

    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);
    }
    

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

    为每种类型的报价创建一个 Controller 是一个好主意(可能有一天会超过 10 个,谁知道?)以避免违反 OCP 或我的设计是错误的?欢迎任何建议、设计更改提示、资源。

    注意:我的报价 Controller 除了保存之外还有许多其他功能。

    最佳答案

    如果您按照您展示的方式进行,我建议您使用单个 Controller 进行报价,并使用 Factory 设计模式来创建您的 $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;    
            }
        }
    }
    

    您可以使用 Controller 方法中的工厂:

    //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);
    }
    

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

    这也将使您的代码 DRY SOLID 因为您不必重复 if/else 语句来在 Controller 的方法中创建对象,因为您将创建对象的责任委托(delegate)给特定的工厂类

    正如下面评论中正确指出的那样,简单工厂将帮助您避免 Controller 中的开/关原则,但请注意,从更一般的角度来看,简单工厂本身就违反了 OCP,因为它使用开关盒。

    无论如何,从我对您的应用程序的了解来看,简单工厂可能是一个很好的解决方案,因为您主要关心的是在许多地方从变量类型构建实例。因此,使用简单工厂,您可以将创建对象的过程“隐藏”到工厂中,并在 Controller 中获取您需要的实例。因此,您仅在开关盒中的工厂内违反了 OCP,但我认为这可能是一个可以承受的权衡

    关于oop - Laravel 中的 SOLID 原理与存储库模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33983038/

    相关文章:

    html - 为什么我的视频背景没有出现,即使代码看起来是正确的?

    python - 生成SQL字符串的设计模式

    ruby - Ruby DSL 与普通 API 的区别

    JavaScript 将函数分配给对象属性

    php - 如何在 PHP 类函数中使用 javascript?

    ruby - 在Ruby中, `self.i`和 `@i`之间有区别吗?

    php - 如何将第三方类库与 Laravel 集成以使其自动加载?

    javascript - 确认删除在 Chrome 中有效,在 Firefox 中无效

    design-patterns - 存储库只是单元测试所必需的吗?

    events - 用高级语言进行的松散编程,如何,为什么以及多少?