3.7. Proxy¶
3.7.1. Intent¶
According to the Gang of Four, the Proxy pattern is a way to “provide a surrogate or placeholder for another object to control access to it” (Design Patterns: Elements of Reusable Object-Oriented Software, 2013, p. 207).
3.7.2. When to use it?¶
Proxy pattern should be used when it’s useful to have a placeholder instead of another object (remote and/or resource hungry actual object, access control, etc.). This has several benefits such as creating objects only on demand or hiding the fact that objects are remote located.
3.7.4. Implementation¶
Employee.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php
namespace Phpatterns\Structural\Proxy;
class Employee
{
const ACCESS_LEVEL_LOW = 0; //no access to WiFi
const ACCESS_LEVEL_HIGH = 1; //access granted to WiFi
/** @var string */
private $firstName;
/** @var string */
private $lastName;
/** @var int */
private $accessLevel;
/**
* @param string $firstName
* @param string $lastName
* @param int $accessLevel
* 0 = No access to WiFi
* 1 = Access granted to WiFi
*/
public function __construct($firstName, $lastName, $accessLevel)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->accessLevel = $accessLevel;
}
/**
* @return int
*/
public function getAccessLevel()
{
return $this->accessLevel;
}
}
|
WifiNetworkInterface.php
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php
namespace Phpatterns\Structural\Proxy;
interface WifiNetworkInterface
{
/**
* Grant access to the WiFi network to an employee
* @param Employee $employee
* @return bool
*/
public function grantAccess(Employee $employee);
}
|
WifiNetwork.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?php
namespace Phpatterns\Structural\Proxy;
class WifiNetwork implements WifiNetworkInterface
{
/** @var string */
private $name;
/**
* @param string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* Grant access to the WiFi network to an employee
* @param Employee $employee
* @return bool
*/
public function grantAccess(Employee $employee)
{
//it's a public network, access granted to everyone!
return true;
}
}
|
WifiNetworkProxy.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?php
namespace Phpatterns\Structural\Proxy;
class WifiNetworkProxy implements WifiNetworkInterface
{
/** @var WifiNetwork */
private $wifiNetwork;
/**
* @param string $name
*/
public function __construct($name)
{
$this->wifiNetwork = new WifiNetwork($name);
}
/**
* Grant access to the WiFi network to an employee
* @param Employee $employee
* @return bool
*/
public function grantAccess(Employee $employee)
{
//now, it's a network with "access control"
if ($employee->getAccessLevel() === Employee::ACCESS_LEVEL_HIGH) {
return $this->wifiNetwork->grantAccess($employee);
}
return false;
}
}
|
3.7.5. Tests¶
ProxyTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <?php
namespace Test\Phpatterns\Structural\Proxy;
use Phpatterns\Structural\Proxy;
class ProxyTest extends \PHPUnit_Framework_TestCase
{
/** @var Proxy\WifiNetworkProxy */
private $wifiNetworkProxy;
/** @var Proxy\WifiNetwork */
private $wifiNetwork;
protected function setUp()
{
$this->wifiNetworkProxy = new Proxy\WifiNetworkProxy("My Company Name Network");
$this->wifiNetwork = new Proxy\WifiNetwork("My Company Name Network");
}
public function testInterfaceImplementation()
{
$this->assertInstanceOf(Proxy\WifiNetworkInterface::class, $this->wifiNetworkProxy);
$this->assertInstanceOf(Proxy\WifiNetworkInterface::class, $this->wifiNetwork);
}
public function testWifiNetworkProxyAccess()
{
$userLowLevel = new Proxy\Employee('John', 'Doe', Proxy\Employee::ACCESS_LEVEL_LOW);
$this->assertFalse($this->wifiNetworkProxy->grantAccess($userLowLevel));
$userHighLevel = new Proxy\Employee('Jason', 'Statham', Proxy\Employee::ACCESS_LEVEL_HIGH);
$this->assertTrue($this->wifiNetworkProxy->grantAccess($userHighLevel));
}
public function testWifiNetworkAccess()
{
$userLowLevel = new Proxy\Employee('Halle', 'Berry', Proxy\Employee::ACCESS_LEVEL_LOW);
$this->assertTrue($this->wifiNetwork->grantAccess($userLowLevel));
$userHighLevel = new Proxy\Employee('Jennifer', 'Lawrence', Proxy\Employee::ACCESS_LEVEL_HIGH);
$this->assertTrue($this->wifiNetwork->grantAccess($userHighLevel));
}
}
|