3.11. Strategy

3.11.1. Terminology:

  • Context (Bağlam)

  • Strategy (Yordam)

  • Concrete Strategy (Somut Yordam)

3.11.2. Amaç

Yordamları ayırarak, aralarındaki hızlı geçişlere olanak sağlamak. Aynı zamanda bu desen, kalıtım (inheritance) için iyi bir alternatiftir (genişletilmiş soyut bir sınıf sahibi olmak yerine).

3.11.3. Örnekler

  • sorting a list of objects, one strategy by date, the other by id

  • simplify unit testing: e.g. switching between file and in-memory storage

3.11.4. UML Diyagramı

Alt Strategy UML Diyagramı

3.11.5. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

Context.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Strategy;
 6
 7class Context
 8{
 9    public function __construct(private Comparator $comparator)
10    {
11    }
12
13    public function executeStrategy(array $elements): array
14    {
15        uasort($elements, [$this->comparator, 'compare']);
16
17        return $elements;
18    }
19}

Comparator.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Strategy;
 6
 7interface Comparator
 8{
 9    /**
10     * @param mixed $a
11     * @param mixed $b
12     */
13    public function compare($a, $b): int;
14}

DateComparator.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Strategy;
 6
 7use DateTime;
 8
 9class DateComparator implements Comparator
10{
11    public function compare($a, $b): int
12    {
13        $aDate = new DateTime($a['date']);
14        $bDate = new DateTime($b['date']);
15
16        return $aDate <=> $bDate;
17    }
18}

IdComparator.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Strategy;
 6
 7class IdComparator implements Comparator
 8{
 9    public function compare($a, $b): int
10    {
11        return $a['id'] <=> $b['id'];
12    }
13}

3.11.6. Test

Tests/StrategyTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Behavioral\Strategy\Tests;
 6
 7use DesignPatterns\Behavioral\Strategy\Context;
 8use DesignPatterns\Behavioral\Strategy\DateComparator;
 9use DesignPatterns\Behavioral\Strategy\IdComparator;
10use PHPUnit\Framework\TestCase;
11
12class StrategyTest extends TestCase
13{
14    public function provideIntegers()
15    {
16        return [
17            [
18                [['id' => 2], ['id' => 1], ['id' => 3]],
19                ['id' => 1],
20            ],
21            [
22                [['id' => 3], ['id' => 2], ['id' => 1]],
23                ['id' => 1],
24            ],
25        ];
26    }
27
28    public function provideDates()
29    {
30        return [
31            [
32                [['date' => '2014-03-03'], ['date' => '2015-03-02'], ['date' => '2013-03-01']],
33                ['date' => '2013-03-01'],
34            ],
35            [
36                [['date' => '2014-02-03'], ['date' => '2013-02-01'], ['date' => '2015-02-02']],
37                ['date' => '2013-02-01'],
38            ],
39        ];
40    }
41
42    /**
43     * @dataProvider provideIntegers
44     *
45     * @param array $collection
46     * @param array $expected
47     */
48    public function testIdComparator($collection, $expected)
49    {
50        $obj = new Context(new IdComparator());
51        $elements = $obj->executeStrategy($collection);
52
53        $firstElement = array_shift($elements);
54        $this->assertSame($expected, $firstElement);
55    }
56
57    /**
58     * @dataProvider provideDates
59     *
60     * @param array $collection
61     * @param array $expected
62     */
63    public function testDateComparator($collection, $expected)
64    {
65        $obj = new Context(new DateComparator());
66        $elements = $obj->executeStrategy($collection);
67
68        $firstElement = array_shift($elements);
69        $this->assertSame($expected, $firstElement);
70    }
71}