我的类依赖于太多其他类,我找不到改进的方法。问题如下:
我有一个ProductRepo、ProductFactory和ImageFactory类。ProductRepo对products表执行数据库操作,并将行作为数组获取。将此数组传递给ProductFactory以创建产品模式。产品模式也有图像链接到它。
客户端代码:
$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;
}
}
所以,我有以下问题:
循环依赖产品报告-->产品工厂-->产品报告
要跳过这一步,我可以使用setter注入或使用代理模式。但我认为这不是一个好的解决方案。你们是怎么处理这种问题的?
- ProductRepo依赖于ProductFactory和ImageFactory。依赖多家工厂是一种好做法吗
我认为问题很明显感谢
根据我的判断,您所做的事情不需要工厂模式,因为您只有一个具有不同细节的产品类,而不是不同类型的图像和产品类。
我建议创建一个带有构造函数的产品类,该构造函数接收来自产品数据库的单行信息和属于它的图像集合。然后构造函数可以设置产品类。
然后,在产品回购类中创建一个产品集合或数组并返回。
类似这样的东西(用伪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接口和几个实现它的类(例如,Circle、Triangle、Rectangle等),它们都使用不同的公式来计算形状的面积。然后,您可以使用工厂为一组公共参数构造和获取特定形状名称的正确实现。
编辑:如果不同的产品类型在功能上有所不同,比如奖励积分的计算方式,你可以这样做:
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;
}
有几种方法可以打破循环依赖关系,但最有趣的问题似乎是ProductFactory需要一个ProductRepo,它本身必须能够构造产品,即使这个功能不会被使用,并且传递一个使用不同工厂的ProductRepo可能没有意义(隐藏规则)。因此:
1) 制作一个只有getImages方法的ImageRepositoryInterface。ProductRepositoryInterface可以扩展此接口,也可以由ProductRepo独立实现。然后,将图像存储库传递到ProductFactoryInterface.make中,而不是在构造时需要它。此时您可以通过ProductRepo。
2) 是的,依赖多种工厂是没有问题的