在保持 SOLID 原则的同时,我对使用具有存储库模式的 Controller 有些困惑。考虑一下,我有两种类型的报价单
并且 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/