加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

php – 向构造函数注入几个参数是不好的做法?

发布时间:2020-05-25 08:53:43 所属栏目:PHP 来源:互联网
导读:我正在开发一个相当复杂的物流管理系统,该系统将继续发展成其他几个与ERP相关的模块.因此,我正在努力实现尽可能多的SRP和开放/封闭原则,以便于扩展和基于域的管理. 因此,我决定使用Laravel和以下模式(不确定它是否有名称): 我将使用PRODUCT对象作为我的示例.

我正在开发一个相当复杂的物流管理系统,该系统将继续发展成其他几个与ERP相关的模块.因此,我正在努力实现尽可能多的SRP和开放/封闭原则,以便于扩展和基于域的管理.

因此,我决定使用Laravel和以下模式(不确定它是否有名称):

我将使用PRODUCT对象作为我的示例.
对象/实体/域具有类
class ProductService {}

此类有一个服务提供程序,它包含在providers数组中,并且也是自动加载的:
ProductServiceServiceProvider

服务提供者实例化(生成)作为接口的ProductRepository.
该接口当前有一个名为EloquentProductRepository实现的MySQL(和一些Eloquent),ProductRepositoryServiceProvider绑定了也加载的实现,并且在providers数组中.

现在,产品与其他域有许多不同的属性和关系,因为其他域(或实体)需要完全分离并再次遵守上述原则(SRP等).我决定对它们也有相同的结构.我为产品做的…我知道有些人可能认为这太多了,但我们需要让系统非常可扩展,说实话我喜欢有条理并且有一个统一的模式(它不需要更多时间,并节省了我很多).

我的问题是这个.处理Product的所有业务逻辑并使“Product”成为现实的ProductService将通过构造函数在创建它的实例时注入几个依赖项.

这就是它目前所拥有的:

namespace EcommerceServicesProduct;

use EcommerceRepositoriesProductProductRepository;
use EcommerceServicesShopEntityShopEntityDescriptionService;
use ContentServicesEntityEntitySEOService;
use ContentServicesEntityEntitySlugService;
use EcommerceServicesTaxTaxService;
use EcommerceServicesProductProductAttributeService;
use EcommerceServicesProductProductCustomAttributeService;
use EcommerceServicesProductProductVolumeDiscountService;
use EcommerceServicesProductProductWeightAttributeService;
use EcommerceServicesProductProductDimensionAttributeService;

/**
 * Class ProductService
 * @package EcommerceServicesProduct
 */
class ProductService {

    /**
     * @var ProductRepository
     */
    protected $productRepo;

    /**
     * @var ShopEntityDescriptionService
     */
    protected $entityDescription;

    /**
     * @var EntitySEOService
     */
    protected $entitySEO;

    /**
     * @var EntitySlugService
     */
    protected $entitySlug;

    /**
     * @var TaxService
     */
    protected $tax;

    /**
     * @var ProductAttributeService
     */
    protected $attribute;

    /**
     * @var ProductCustomAttributeService
     */
    protected $customAttribute;

    /**
     * @var ProductVolumeDiscountService
     */
    protected $volumeDiscount;

    /**
     * @var ProductDimensionAttributeService
     */
    protected $dimension;

    /**
     * @var ProductWeightAttributeService
     */
    protected $weight;

    /**
     * @var int
     */
    protected $entityType = 3;


    public function __construct(ProductRepository $productRepo,ShopEntityDescriptionService $entityDescription,EntitySEOService $entitySEO,EntitySlugService $entitySlug,TaxService $tax,ProductAttributeService $attribute,ProductCustomAttributeService $customAttribute,ProductVolumeDiscountService $volumeDiscount,ProductDimensionAttributeService $dimension,ProductWeightAttributeService $weight)
    {
        $this->productRepo = $productRepo;
        $this->entityDescription = $entityDescription;
        $this->entitySEO = $entitySEO;
        $this->entitySlug = $entitySlug;
        $this->tax = $tax;
        $this->attribute = $attribute;
        $this->customAttribute = $customAttribute;
        $this->volumeDiscount = $volumeDiscount;
        $this->dimension = $dimension;
        $this->weight = $weight;
    }
`

将尽可能多的参数传递给PHP中的构造函数是不好的做法(请忽略服务的长名称,因为这些名称在确定ERP名称空间时可能会发生变化)?

正如下面Ben所回答的,在这种情况下它不是.我的问题与OOP无关,但更多与性能等有关.原因在于,这个特殊的类ProductService是web deves用控制器做的事情,即他们可能(并且反对原则)在一个ProductController中添加所有数据库关系.处理存储库服务(db等..)并附加关系,然后突然变成你的业务逻辑.

在我的应用程序中(我以这种方式看到大多数应用程序),Web层只是另一层. MVC负责Web层,有时也处理其他Apis,但除了与MVC中的视图和JS框架相关之外,我不会有任何逻辑.所有这一切都在我的软件中.

总结:我知道这是一个非常SOLID的设计,依赖注入并且它们确实是依赖关系(即产品必须有税,产品确实有重量等等)并且它们可以很容易地与其他类交换,这要归功于接口和ServiceProviders.现在感谢答案,我也知道在构造函数中注入这么多依赖项是可以的.

我最后会写一篇关于我使用的设计模式以及为什么我在不同场景中使用它们的文章,所以如果你对此感兴趣,请关注我.

感谢大家

一般来说,不,在大多数情况下,这不是一个坏习惯.但是在你的情况下,正如@zerkms的评论中所说,看起来你的类依赖于很多依赖,你应该调查它,并考虑如何最小化依赖,但如果你实际上使用他们应该在那里,我根本没有看到任何问题.

但是,您应该使用依赖注入容器(DIC).

依赖注入容器,基本上是一个由您提供的命名空间创建类的工具,它创建包含所有依赖项的实例.您还可以共享对象,因此在创建依赖项时不会创建它的新实例.

我建议你Auryn DIC

用法:

$provider = new Provider();
 $class = $provider->make("MyAppMyClass");

这里发生的是:

namespace MyApp;

use DependenciesDependencyOne,DependenciesDependencyTwo,DependenciesDependencyThree;

class MyClass {

    public function __construct(DependencyOne $one,Dependency $two,DependencyThree $three) {
         // .....
    }
}

基本上,Provider#make(namespace)创建给定命名空间的实例,并创建它的consturctor参数和所有参数的构造函数参数等所需的实例.

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读