2.10. Proxy

2.10.1. Amaç

Maliyetli olan veya yinelenmesi (duplicate) mümkün olmayan bir şeyi arayüzlemek.

2.10.2. Örnekler

  • Doctrine2, kullanıcı kendi varlık sınıflarını (entity class) kullanırken ve asla aracıları kullanmaz ya da aracılara dokunmazken, framework içindeki özel yöntemleri (magic method) (örn: yavaş başlatım (lazy initialization)) uygulamak için aracıları kullanır.

2.10.3. UML Diyagramı

Alt Proxy UML Diyagramı

2.10.4. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

BankAccount.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\Proxy;
 6
 7interface BankAccount
 8{
 9    public function deposit(int $amount);
10
11    public function getBalance(): int;
12}

HeavyBankAccount.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\Proxy;
 6
 7class HeavyBankAccount implements BankAccount
 8{
 9    /**
10     * @var int[]
11     */
12    private array $transactions = [];
13
14    public function deposit(int $amount)
15    {
16        $this->transactions[] = $amount;
17    }
18
19    public function getBalance(): int
20    {
21        // this is the heavy part, imagine all the transactions even from
22        // years and decades ago must be fetched from a database or web service
23        // and the balance must be calculated from it
24
25        return array_sum($this->transactions);
26    }
27}

BankAccountProxy.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\Proxy;
 6
 7class BankAccountProxy extends HeavyBankAccount implements BankAccount
 8{
 9    private ?int $balance = null;
10
11    public function getBalance(): int
12    {
13        // because calculating balance is so expensive,
14        // the usage of BankAccount::getBalance() is delayed until it really is needed
15        // and will not be calculated again for this instance
16
17        if ($this->balance === null) {
18            $this->balance = parent::getBalance();
19        }
20
21        return $this->balance;
22    }
23}

2.10.5. Test

ProxyTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Structural\Proxy\Tests;
 6
 7use DesignPatterns\Structural\Proxy\BankAccountProxy;
 8use PHPUnit\Framework\TestCase;
 9
10class ProxyTest extends TestCase
11{
12    public function testProxyWillOnlyExecuteExpensiveGetBalanceOnce()
13    {
14        $bankAccount = new BankAccountProxy();
15        $bankAccount->deposit(30);
16
17        // this time balance is being calculated
18        $this->assertSame(30, $bankAccount->getBalance());
19
20        // inheritance allows for BankAccountProxy to behave to an outsider exactly like ServerBankAccount
21        $bankAccount->deposit(50);
22
23        // this time the previously calculated balance is returned again without re-calculating it
24        $this->assertSame(30, $bankAccount->getBalance());
25    }
26}