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

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)

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

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

Nginx rewrite rules for hosting angular(any) static app on subroute

Hi everyone, I decided to reorganise my personal blog and use it mostly as "Notes" Today, I want to host two websites served by golang application. The simplest solution is to create system service which points to go executable app on the particular port. In a nutshell, there are two separate services which use 9990 and 9991 ports. Next step I added this simple rule to the Nginx location /admin { rewrite /admin/(.*) /$1 break; proxy_pass http://localhost:9991; proxy_redirect off; proxy_set_header Host $host; } location / { proxy_pass http://localhost:9990; } So this simple configuration just rewrites URL properly to the admin service and I do not need to add extra `admin` route prefix. The latest step is set-up base href for the static `index.html` file. We can easily do it with build option `ng build --base-href /admin/` Thank everyone for reading.