Design Patterns PHP - Composite Java

1) What have we done ?

As we said we create the common interface "Product"

Previous concrete class "Product" now we will call "SingleProduct"


interface Product
{
    public function getCost();
}

class SingleProduct implements Product
{
    /**
     * @var double
     */
    protected $cost;

    function __construct($cost)
    {
        $this->cost = $cost;
    }

    /**
     * @return double
     */
    public function getCost()
    {
        return $this->cost;
    }
}

class Pack implements Product
{
    /**
     * @var Product []
     */
    private $products = [];

    /**
     * @param Product []
     */
    function __construct($products)
    {
        $this->products = $products;
    }

    /**
     * @return double
     */
    public function getCost()
    {
        $cost = 0;
        foreach ($this->products as $product) {
            $cost += $product->getCost();
        }

        return $cost;
    }
}




2) What have we achieved ?

Let's look on client code


$singleProduct = new SingleProduct(13.02);
$pack = new Pack([new SingleProduct(13.02), new SingleProduct(5.67), new SingleProduct(5.67), new SingleProduct(5.67), new SingleProduct(2.12)]);
$megaPack = new Pack([new Pack([new SingleProduct(4.32), new SingleProduct(11.62)]), new SingleProduct(2.35)]);

$products = [$singleProduct, $pack, $megaPack];

$product = $products[random(0, 2)];

$cost = $product->getCost();




We don't have to to check types, Client doesn't have to differentiate type "Pack" and "SingleProduct".

Therein lies "Composite" pattern. It allows objects with relation whole-part treat compound and single object in the same way.

Let's notice that now when we treat these objects the same we can create more compound objects like megaPack.
Before we couldn't do this, it's another plus.