<?php
interface Downloader
{
public function download(string $url): string;
}
class SimpleDownloader implements Downloader
{
public function download(string $url): string
{
echo "Downloading a file from the Internet.\n";
$result = file_get_contents($url);
echo "Downloaded bytes: " . strlen($result) . "\n";
return $result;
}
}
class CachingDownloader implements Downloader
{
/**
* @var SimpleDownloader
*/
private $downloader;
/**
* @var string[]
*/
private $cache = [];
public function __construct(SimpleDownloader $downloader)
{
$this->downloader = $downloader;
}
public function download(string $url): string
{
if (!isset($this->cache[$url])) {
echo "CacheProxy MISS. ";
$result = $this->downloader->download($url);
$this->cache[$url] = $result;
} else {
echo "CacheProxy HIT. Retrieving result from cache.\n";
}
return $this->cache[$url];
}
}
// USAGE
$simpleDownload = new SimpleDownloader;
$simpleDownload->download("http://example.com/");
$proxy = new CachingDownloader($simpleDownload);
$proxy->download("http://example.com/");
<?php
interface BankAccount
{
public function deposit(int $amount);
public function getBalance(): int;
}
class HeavyBankAccount implements BankAccount
{
/**
* @var int[]
*/
private array $transactions = [];
public function deposit(int $amount)
{
$this->transactions[] = $amount;
}
public function getBalance(): int
{
// this is the heavy part, imagine all the transactions even from
// years and decades ago must be fetched from a database or web service
// and the balance must be calculated from it
return (int) array_sum($this->transactions);
}
}
class BankAccountProxy extends HeavyBankAccount implements BankAccount
{
private ?int $balance = null;
public function getBalance(): int
{
// because calculating balance is so expensive,
// the usage of BankAccount::getBalance() is delayed until it really is needed
// and will not be calculated again for this instance
if ($this->balance === null) {
$this->balance = parent::getBalance();
}
return $this->balance;
}
}
// USAGE
$bankAccount = new BankAccountProxy();
$bankAccount->deposit(30);
echo $bankAccount->getBalance(); // 30
$bankAccount->deposit(120);
echo $bankAccount->getBalance(); // still 30, because cached due to proxy
<?php
interface File {
public function add (string $name, string $path): void;
public function get (string $name): void;
public function remove (string $name): void;
}
class FileProvider implements File {
public function add (string $name, string $path): void {
echo "File {$name} from {$path} was added to storage" . PHP_EOL;
}
public function get (string $name): void {
echo "File {$name} was downloaded from storage" . PHP_EOL;
}
public function remove (string $name): void {
echo "File {$name} was removed from storage" . PHP_EOL;
}
}
class AuthFile implements File {
const ALLOWED_USERS = [
"AAA",
];
private $file;
public function __construct (File $file) {
$this->file = $file;
}
public function add (string $name, string $path): void {
if ($this->loggedIn()) {
$this->file->add($name, $path);
}
}
public function get (string $name): void {
if ($this->loggedIn()) {
$this->file->get($name);
}
}
public function remove (string $name): void {
if ($this->loggedIn()) {
$this->file->remove($name);
}
}
private function loggedIn () {
if (isset($_SESSION["username"]) && in_array($_SESSION["username"], self::ALLOWED_USERS)) {
echo "User can perform action" . PHP_EOL;
return true;
} else {
echo "User can not perform action" . PHP_EOL;
return false;
}
}
}
class User {
public function login ($name) {
echo "Logging in as {$name}" . PHP_EOL;
$_SESSION["username"] = $name;
}
public function logOut () {
echo "Logging out" . PHP_EOL;
unset($_SESSION["username"]);
}
}
session_start();
$provider = new FileProvider();
$fileAuth = new AuthFile($provider);
$fileAuth->add("test-file.png", "/home/ubuntu");
$fileAuth->remove("test-file.png");
$fileAuth->get("test-file.png");
$auth = new User();
$auth->login("AAA");
$fileAuth->add("test-file.png", "/home/ubuntu");
$fileAuth->remove("test-file.png");
$fileAuth->get("test-file.png");
$auth->logOut();
$auth->login("BBB");
$fileAuth->add("test-file.png", "/home/ubuntu");
$fileAuth->remove("test-file.png");
$fileAuth->get("test-file.png");
session_destroy();
/*
File test-file.png from /home/ubuntu was added to storage
File test-file.png was removed from storage
File test-file.png was downloaded from storage
Logging in as AAA
User can perform action
File test-file.png from /home/ubuntu was added to storage
User can perform action
File test-file.png was removed from storage
User can perform action
File test-file.png was downloaded from storage
Logging out
Logging in as BBB
User can not perform action
User can not perform action
User can not perform action
*/
<?php
abstract class ReadFileAbstract
{
protected $fileName;
protected $contents;
public function getFileName()
{
return $this->fileName;
}
public function setFileName($fileName)
{
$this->fileName = $fileName;
}
public function getContents()
{
return $this->contents;
}
}
lass ReadFile extends ReadFileAbstract
{
const DOCUMENTS_PATH = "/home/simon";
public function __construct($fileName)
{
$this->setFileName($fileName);
$this->contents = file_get_contents(self::DOCUMENTS_PATH . "/" . $this->fileName);
}
}
class ReadFileProxy extends ReadFileAbstract
{
private $file;
public function __construct($fileName)
{
$this->fileName = $fileName;
}
public function lazyLoad()
{
if ($this->file === null) {
$this->file = new ReadFile($this->fileName);
}
return $this->file;
}
}
// usage
$proxies = array();
for ($i = 0; $i < 10; $i++) {
// tell the proxy which file should be read (when lazy loaded)
$proxies[$i] = new ReadFileProxy("file" . $i . ".txt");
}
// Now it's time to read the contents of file3.txt
$file3 = $proxies[3]->lazyLoad();
// echo the contents of file3.txt
echo $file3->getContents();