Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

lazy-loading-value-holder.md

Zuletzt modifiziert: 09.10.2024, 12:56 - Dateigröße: 6.40 KiB


 001  # Lazy Loading Value Holder Proxy
 002   
 003  A lazy loading value holder proxy is a virtual proxy that wraps and lazily initializes a "real" instance of the proxied
 004  class.
 005   
 006  ## What is lazy loading?
 007   
 008  In pseudo-code, in userland, [lazy loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) looks like following:
 009   
 010  ```php
 011  class MyObjectProxy
 012  {
 013      private $wrapped;
 014   
 015      public function doFoo()
 016      {
 017          $this->init();
 018   
 019          return $this->wrapped->doFoo();
 020      }
 021   
 022      private function init()
 023      {
 024          if (null === $this->wrapped) {
 025              $this->wrapped = new MyObject();
 026          }
 027      }
 028  }
 029  ```
 030   
 031  This code is problematic, and adds a lot of complexity that makes your unit tests' code even worse.
 032   
 033  Also, this kind of usage often ends up in coupling your code with a particular
 034  [Dependency Injection Container](http://martinfowler.com/articles/injection.html)
 035  or a framework that fetches dependencies for you.
 036  That way, further complexity is introduced, and some problems related
 037  with service location raise, as I've explained
 038  [in this article](http://ocramius.github.com/blog/zf2-and-symfony-service-proxies-with-doctrine-proxies/).
 039   
 040  Lazy loading value holders abstract this logic for you, hiding your complex, slow, performance-impacting objects behind
 041  tiny wrappers that have their same API, and that get initialized at first usage.
 042   
 043  ## When do I use a lazy value holder?
 044   
 045  You usually need a lazy value holder in cases where following applies
 046   
 047   * your object takes a lot of time and memory to be initialized (with all dependencies)
 048   * your object is not always used, and the instantiation overhead can be avoided
 049   
 050  ## Usage examples
 051   
 052  [ProxyManager](https://github.com/Ocramius/ProxyManager) provides a factory that eases instantiation of lazy loading
 053  value holders. To use it, follow these steps:
 054   
 055  First of all, define your object's logic without taking care of lazy loading:
 056   
 057  ```php
 058  namespace MyApp;
 059   
 060  class HeavyComplexObject
 061  {
 062      public function __construct()
 063      {
 064          // just write your business logic
 065          // don't worry about how heavy initialization of this will be!
 066      }
 067   
 068      public function doFoo() {
 069          echo "OK!"
 070      }
 071  }
 072  ```
 073   
 074  Then use the proxy manager to create a lazy version of the object (as a proxy):
 075   
 076  ```php
 077  namespace MyApp;
 078   
 079  use ProxyManager\Factory\LazyLoadingValueHolderFactory;
 080  use ProxyManager\Proxy\LazyLoadingInterface;
 081   
 082  require_once __DIR__ . '/vendor/autoload.php';
 083   
 084  $factory     = new LazyLoadingValueHolderFactory();
 085  $initializer = function (& $wrappedObject, LazyLoadingInterface $proxy, $method, array $parameters, & $initializer) {
 086      $initializer   = null; // disable initialization
 087      $wrappedObject = new HeavyComplexObject(); // fill your object with values here
 088   
 089      return true; // confirm that initialization occurred correctly
 090  };
 091   
 092  $instance = $factory->createProxy('MyApp\HeavyComplexObject', $initializer);
 093  ```
 094   
 095  You can now simply use your object as before:
 096   
 097  ```php
 098  // this will just work as before
 099  $proxy->doFoo(); // OK!
 100  ```
 101   
 102  ## Lazy Initialization
 103   
 104  As you can see, we use a closure to handle lazy initialization of the proxy instance at runtime.
 105  The initializer closure signature should be as following:
 106   
 107  ```php
 108  /**
 109   * @var object  $wrappedObject the instance (passed by reference) of the wrapped object,
 110   *                             set it to your real object
 111   * @var object  $proxy         the instance proxy that is being initialized
 112   * @var string  $method        the name of the method that triggered lazy initialization
 113   * @var string  $parameters    an ordered list of parameters passed to the method that
 114   *                             triggered initialization, indexed by parameter name
 115   * @var Closure $initializer   a reference to the property that is the initializer for the
 116   *                             proxy. Set it to null to disable further initialization
 117   *
 118   * @return bool true on success
 119   */
 120  $initializer = function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {};
 121  ```
 122   
 123  The initializer closure should usually be coded like following:
 124   
 125  ```php
 126  $initializer = function (& $wrappedObject, $proxy, $method, $parameters, & $initializer) {
 127      $newlyCreatedObject = new Foo(); // instantiation logic
 128      $newlyCreatedObject->setBar('baz') // instantiation logic
 129      $newlyCreatedObject->setBat('bam') // instantiation logic
 130   
 131      $wrappedObject = $newlyCreatedObject; // set wrapped object in the proxy
 132      $initializer   = null; // disable initializer
 133   
 134      return true; // report success
 135  };
 136  ```
 137   
 138  The
 139  [`ProxyManager\Factory\LazyLoadingValueHolderFactory`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Factory/LazyLoadingValueHolderFactory.php)
 140  produces proxies that implement both the
 141  [`ProxyManager\Proxy\ValueHolderInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Proxy/ValueHolderInterface.php)
 142  and the
 143  [`ProxyManager\Proxy\LazyLoadingInterface`](https://github.com/Ocramius/ProxyManager/blob/master/src/ProxyManager/Proxy/LazyLoadingInterface.php).
 144   
 145  At any point in time, you can set a new initializer for the proxy:
 146   
 147  ```php
 148  $proxy->setProxyInitializer($initializer);
 149  ```
 150   
 151  In your initializer, you currently **MUST** turn off any further initialization:
 152   
 153  ```php
 154  $proxy->setProxyInitializer(null);
 155  ```
 156   
 157  or
 158   
 159  ```php
 160  $initializer = null; // if you use the initializer by reference
 161  ```
 162   
 163  ## Triggering Initialization
 164   
 165  A lazy loading proxy is initialized whenever you access any property or method of it.
 166  Any of the following interactions would trigger lazy initialization:
 167   
 168  ```php
 169  // calling a method
 170  $proxy->someMethod();
 171   
 172  // reading a property
 173  echo $proxy->someProperty;
 174   
 175  // writing a property
 176  $proxy->someProperty = 'foo';
 177   
 178  // checking for existence of a property
 179  isset($proxy->someProperty);
 180   
 181  // removing a property
 182  unset($proxy->someProperty);
 183   
 184  // cloning the entire proxy
 185  clone $proxy;
 186   
 187  // serializing the proxy
 188  $unserialized = serialize(unserialize($proxy));
 189  ```
 190   
 191  Remember to call `$proxy->setProxyInitializer(null);` to disable initialization of your proxy, or it will happen more
 192  than once.
 193   
 194  ## Proxying interfaces
 195   
 196  You can also generate proxies from an interface FQCN. By proxying an interface, you will only be able to access the
 197  methods defined by the interface itself, even if the `wrappedObject` implements more methods. This will anyway save
 198  some memory since the proxy won't contain useless inherited properties.
 199   
 200  ## Tuning performance for production
 201   
 202  See [Tuning ProxyManager for Production](https://github.com/Ocramius/ProxyManager/blob/master/docs/tuning-for-production.md).
 203