0

我的课程依赖于太多其他课程,我找不到改进它的方法。问题如下:

我有一个 ProductRepo、ProductFactory 和一个 ImageFactory 类。ProductRepo 对产品表执行 db 操作并将行作为数组获取。这个数组被传递给 ProductFactory 来创建一个 Product Modal。产品模式也有与之链接的图像。

客户端代码:

$products = $this->productRepo->findAll('...');
foreach($products as $product){
    ...
    //get images
    $images = $product->getImages();
    ...
}

Class ProductRepo implements ProductRepositoryInterface{
    protected $productFactory;
    protected $imageFactory;
    public function __construct(ProductFactoryInterface $productFactory, ImageFactoryInterface $imageFactory)
    {
        $this->productFactory = $productFactory;
        $this->imageFactory = $imageFactory;
    }

    public function findAll(...)
    {
        $result = $this->execute('....');
        $products = $this->productFactory->make($result);
        return $products;
    }

    public function getImages($productId)
    {
        $result = $this->execute('....');
        $images = $this->imageFactory->make($result);
        return $images;
    }
}

Class ProductFactory implements ProductFactoryInterface{
    protected $productRepo;
    public function __construct(ProductRepositoryInterface $productRepo)
    {
        $this->productRepo = $productRepo;
    }

    public function make($items)
    {
        ...
        $products = [];
        foreach($items as $item){
            $product = new Product($item);
            $item->setImages($this->productRepo->getImages($product->getId()));
            $products[] = $product;
        }
        ...
        return $products;
    }
}

Class ImageFactory implements ImageFactoryInterface{
    public function make($items)
    {
        ...
        $images = [];
        foreach($items as $item){
            $image = new Image($item);
            $images[] = $image;
        }
        ...
        return $images;
    }
}

所以,我有以下问题:

  1. 循环依赖 ProductRepo --> ProductFactory --> ProductRepo

    要跳过这个,我可以使用 setter 注入或使用代理模式。但我认为这不是一个好的解决方案。遇到这样的问题,大家是怎么处理的?

  2. ProductRepo 依赖于 ProductFactory 和 ImageFactory。依赖多个工厂是一种好习惯吗?

我认为问题很清楚。:) 谢谢

4

2 回答 2

2

根据我的判断,您不需要工厂模式来做您正在做的事情,而不是不同类型的图像和产品类别,您只有一个具有不同细节的产品类别。

我建议使用构造函数创建单个产品类,该构造函数从产品数据库接收单行信息以及属于它的图像集合。然后构造函数可以设置产品类。

然后,在产品 repo 类中创建一个产品集合或数组并将其返回。

像这样的东西(用伪php编写)

    Class Product
    {
        public function __construct(productInfo, imageArray)
        {
            //contruct product here
        }
    }

    Class ProductRepo
    {

        public function getProducts()
        {
            //retrieve products
            $items = getProducts();

            //setup products
            return setupProducts($items);
        }

        private function setupProducts($items)
        {

            foreach($items as $item){
                $images = $this->getImages($product->getId());

                $product = new Product($item, $images);

                $products[] = $product;
        }
            return $products;
        }

        private function getImages($itemId)
        {
            //get and return images for this product
        }

        private function loadProducts()
        {
            //load from database and return all products
        }
    }

工厂模式适用于需要在具体对象中实现具有不同功能的接口的多个实现并且需要一种方法来选择正确的接口的情况。例如,如果您有一个尝试计算各种形状面积的应用程序,您可能有一个带有 calculateArea() 函数的 IShapes 接口和几个实现它的类(例如,圆形、三角形、矩形等)都使用不同的公式来计算形状的面积。然后,您可以使用工厂为一组通用参数构造和获取特定形状名称的正确实现。

编辑:如果不同产品类型之间在功能上有所不同,例如奖励积分的计算方式,您可以执行以下操作:

    class ProductFactory
    {
        public Iproduct getProduct($productType, $productInfo, $images)
        {
            switch(productType)
            {
                case: featured
                    return new featuredProduct($productInfo)
                case: standard
                    return new standardProduct($productInfo)
            }
        }
    }

    Interface Iproducts
    {
        //suppose different product types have different reward point formula's
        calculateRewardPoints();

        ....
        //other functions
    }

然后可以在上面的产品仓库中使用,如下所示:

    private function setupProducts($items)
    {
        foreach($items as $item){
        $images = $this->getImages($product->getId());

            $product = ProductFactory.getProduct($item.type, $item, $images);

            $products[] = $product;
    }
于 2015-12-25T18:21:24.447 回答
1

有几种方法可以打破循环依赖,但最根本的问题似乎是 ProductFactory 需要一个 ProductRepo,它本身必须能够构造产品,即使这个功能不会被使用并且它可能没有意义传递使用不同工厂的 ProductRepo(隐藏规则)。所以:

1) 制作一个只有 getImages 方法的 ImageRepositoryInterface。ProductRepositoryInterface 可以扩展这个接口或者 ProductRepo 可以独立实现它。然后,将图像存储库传递给 ProductFactoryInterface.make,而不是在构建时要求它。此时您可以传递您的 ProductRepo。

2)是的,依赖一种以上的工厂没有问题

于 2015-12-25T18:25:03.983 回答