Skip to main content

PHP Design Patterns - Strategy

Today I want to explain how to use strategy design pattern in PHP. I tried to use this pattern when I want decouple algorithms for calculating something at runtime. For example, we can dynamically changing methods which will be calculate price of some items using some logic.

Create car, for example:
namespace strategy;

abstract class Item{
    abstract function getPrice();
}

class Car extends Item{

    protected  $price;
    public $name;
    protected $isTuned;

    public function __construct($name, $price, $isTuned){
        $this->name = $name;
        $this->price = $price;
        $this->isTuned = $isTuned;
    }

    /**
     * @return bool
     */
    public function isTuned(){
        return $this->isTuned;
    }

    public function getPrice(){
        return $this->price;
    }
}

Suppose we want to separate method which will calculate price with different strategies. Create interface
which will be implemented in each strategy.
namespace strategy;

interface IPriceStrategy {
    /**
     * @param Item[] $items
     * @return mixed
     */
public function calculatePrice(array $items);
}


Now we can create simple discount strategy for calculating.

class DiscountStrategy implements IPriceStrategy
{

    private $discount = 0;

    /**
     * @param $discount - in percent
     * @throws \Exception
     */
    public function __construct($discount)
    {
        if ($discount < 0) throw new \Exception('Discount must be greater or equal 0');
        $this->discount = $discount;
    }

    /**
     * @param Item[] $items
     * @return mixed
     */
    public function calculatePrice(array $items)
    {
        $price = 0;
        foreach ($items as $item) {
            $price = $price + $item->getPrice();
        }

        return $price * ($this->discount / 100);
    }
}


And implement second strategy - if invoice has more than some quantity of cars we subtract percents from total bill.
class DiscountManyCars implements IPriceStrategy
{
    private $discount;
    private $discountQuantities;

    public function __construct($discount, $discountQuantities)
    {
        $this->discount = $discount;
        $this->discountQuantities = krsort($discountQuantities);
    }

    /**
     * @param Item[] $items
     * @return mixed
     */
    public function calculatePrice(array $items)
    {
        $count = count($items);
        $price = 0;
        foreach ($items as $item) {
            $price = $price + $item->getPrice();
        }

        if ($count >= $this->discountQuantities) {
            $price = $price * ($this->discount / 100);
        }

        return $price;
    }
}

And finally using strategy pattern:
namespace strategy;

require_once 'Car.php';
require_once 'Invoice.php';
require_once 'IPriceStrategy.php';

$invoice = new Invoice();
$car1 = new Car('BMV', 1200000, false);
$car2 = new Car('MERCEDES', 100000, true);
$car3 = new Car('AUDI', 300000, false);

$invoice->addCar($car1);
$invoice->addCar($car2);
$invoice->addCar($car2);
$invoice->addCar($car2);
$invoice->addCar($car2);
$invoice->addCar($car3);
$invoice->addCar($car3);
$invoice->addCar($car3);

$discountStrategy = new DiscountStrategy(20);
$manyDiscountStrategy = new DiscountManyCars(30, 6);

$priceOne = $invoice->calculatePrice($discountStrategy);
$priceTwo = $invoice->calculatePrice($manyDiscountStrategy);
setlocale(LC_MONETARY, 'en_US');
$fmt = new \NumberFormatter('en_US', \NumberFormatter::CURRENCY);
echo "first strategy: ", $fmt->formatCurrency($priceOne, "EUR"), "
"; echo "second strategy: ", $fmt->formatCurrency($priceTwo, "EUR"), "
";

Output:
first strategy: €500,000.00
second strategy: €750,000.00

Comments

Popular posts from this blog

Університет нафти і газу

Всім привіт. Я поступив в національний технічний університет Нафти і Газу. Поступив на 2 курс, хоча мав б бути на третьому. Я дякую, за те, що поступив на другий курс на держ. форму. Але не все так просто. Потрібно перезаразувати години предметів, які вчили в універі на 1 і частково на 2 курсі, для того щоб без проблем перейти на 3 курс. На рахунок програмування, майже нічого нового немає. Хіба що будем вчити Java на на предметі "технологія розробки ПЗ". Ось і все, що я хотів написати. Всім удачі!

Some notes about transportation problem

Hello guys. After work I remembered my studying at university. My first thoughts is about solving Monge–Kantorovich transportation problem using a modification of simplex method known as Method of Potentials. Transportation theory investigates methods for optimal allocation resources among consumers and transportation them with minimum cost. For example, suppose we have some factories which provide materials and shops which consume it. (To be continued)

Docker multi-stage build in Action

Hi everyone, today I want to show how to create the small docker image for deploying the application. I've an application which consists of a backend(go application) and angular based front-end application. So let's create the Dockerfile and step by step fill it with commands. I started with frontend Next I added the golang builder For avoiding, the certificate signed by unknown authority error during HTTP request I add trusted certificates (details more here Stackoverflow issue ) Finally, copy all items to the end image I keep my container on the quay.io so everyone can see logs and pull the container docker pull quay.io/vdzundza/shoper All Dockerfile listing here Github Gist Thanks everyone !