The next structural design pattern in this series is called the proxy pattern. You can think of these, just like any other proxy. The aim here is to create a class which takes full responsibility for the execution of another class.
Yup you got it… technically they are wrappers as well, however they aren’t labelled this way.
What is the proxy pattern
The proxy pattern is a way of creating an intermediary between your client/controller and your subject class. Think of a HTTP proxy, which is a gateway between your browser (client) and a server (subject). These proxies can be used to enhance a user experience by caching data, removing adverts, allowing access to restricted content 😛 plus much more. The proxy pattern has the similar goals and so can be used to simplify, optimise and enhance existing subjects (classes).
When to use the proxy pattern
I stated above that the proxy pattern can simplify, optimise and enhance existing subjects. This is completely true, but I want to focus on optimisation. If the main goal of your new class is to simplify or enhance, you may be better off using a facade or a decorator respectively. Saying that…. simplifications and enhancements are good additions to a proxy focusing on optimisation.
One of the main optimisation use cases for the proxy pattern is lazy initialisation of your subject. What this means is, instead of initialising your subject in the client. The client would initialise the proxy and the proxy would only initialise the subject when required. This is most useful when your subject initialisation does a large amount of setup that potentially the client will never need.
Rules
- The subject class and the proxy class should implement the same interface.
Advantages
- Using proxies can optimise your application by only loading resources which are required.
- Using a proxy class can make your implementation cleaner and easier to maintain.
Example
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; } } class 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; } } $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();
What just happened here
As described above, one of the proxy pattern use cases is to lazy load resources. In this case, it’s the file contents which are being lazy loaded. Inside the for loop, 10 instances to the ReadFileProxy class are created, however the file content of file 3, is only read on a call to the lazyLoad() method. This means the 9 other proxy objects that were created, didn’t need to perform slow read operations on the file system.
11 Love This
Pingback: My Homepage