0

私のクラスはあまりにも多くの他のクラスに依存しており、それを改善する方法が見つかりませんでした。問題は次のようになります。

ProductRepo、ProductFactory、および ImageFactory クラスがあります。ProductRepo は、products テーブルで 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

さまざまなタイプの画像や製品クラスではなく、詳細が異なる1つの製品クラスしかないので、私が言えることから、あなたがしていることにはファクトリーパターンは必要ありません。

製品データベースから 1 行の情報とそれに属する画像のコレクションを受け取るコンストラクターを使用して、1 つの製品クラスを作成することをお勧めします。その後、コンストラクターは製品クラスをセットアップできます。

次に、製品リポジトリ クラスで製品のコレクションまたは配列を作成し、それを返します。

このようなもの(疑似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() 関数とそれを実装するいくつかのクラス (たとえば、Circle、Triangle、Rectangle など) を備えた 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 に答える