note 99446 added to language.oop5.patterns

From: Date: Wed, 18 Aug 2010 09:05:44 +0000
Subject: note 99446 added to language.oop5.patterns
Groups: php.notes 
Request: Send a blank email to php-notes+get-171792@lists.php.net to get a copy of this message
I've come up with an interesting and intuitive way to define a generic Factory class. It's basically an empty object that remembers all operations you perform on it. You can then request an actual instance, and all operations are repeated on that instance. The order of the operations is preserved. <?php # If you want a factory that initializes an object like this: $myobject = new MyObject('arg1', 'arg2'); $myobject->doFooBar(); $myobject->baz = 10; # You write: $f_myobject = new MagicFactory('MyObject', 'arg1', 'arg2'); $f_myobject->doFooBar(); $f_myobject->baz = 10; # You can now get the same object like this: $myobject = $f_myobject->instance(); ?> <?php /** * Generic Factory class * * This Magic Factory will remember all operations you perform on it, * and apply them to the object it instantiates. * */ class MagicFactory { private $history, $class, $constructor_args; /** * Create a factory of given class. Accepts extra arguments to be passed to * class constructor. */ function __construct( $class ) { $args = func_get_args(); $this->class = $class; $this->constructor_args = array_slice( $args, 1 ); } function __call( $method, $args ) { $this->history[] = Array( 'action' => 'call', 'method' => $method, 'args' => $args ); } function __set( $property, $value ) { $this->history[] = Array( 'action' => 'set', 'property' => $property, 'value' => $value ); } /** * Creates an instance and performs all operations that were done on this MagicFactory */ function instance() { # use Reflection to create a new instance, using the $args $reflection_object = new ReflectionClass( $this->class ); $object = $reflection_object->newInstanceArgs( $this->constructor_args ); # Alternative method that doesn't use ReflectionClass, but doesn't support variable # number of constructor parameters. //$object = new $this->class(); # Repeat all remembered operations, apply to new object. foreach( $this->history as $item ) { if( $item['action'] == 'call' ) { call_user_func_array( Array( $object, $item['method'] ), $item['args'] ); } if( $item['action'] == 'set' ) { $object->{$item['property']} = $item['value']; } } # Done return $object; } } ?> Example: <?php class Person { private $name, $sirname; public $age; function __construct( $name, $sirname ) { $this->name = $name; $this->sirname = $sirname; } function setName( $name ) { $this->name = $name; } function introduce() { print "Hello, my name is {$this->name} {$this->sirname}! I'm {$this->age} years old."; } } # Setup a factory $person_factory = new MagicFactory('Person', 'John', 'Johnson'); $person_factory->setName('Jack'); $person_factory->age = 55; # Get an instance $jack = $person_factory->instance(); $jack->introduce(); # Prints: # Hello, my name is Jack Johnson! I'm 55 years old ---- Server IP: 69.147.83.197 Probable Submitter: 192.87.139.139 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.patterns.php Edit -- https://master.php.net/note/edit/99446 Del: integrated -- https://master.php.net/note/delete/99446/integrated Del: useless -- https://master.php.net/note/delete/99446/useless Del: bad code -- https://master.php.net/note/delete/99446/bad+code Del: spam -- https://master.php.net/note/delete/99446/spam Del: non-english -- https://master.php.net/note/delete/99446/non-english Del: in docs -- https://master.php.net/note/delete/99446/in+docs Del: other reasons-- https://master.php.net/note/delete/99446 Reject -- https://master.php.net/note/reject/99446 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#171792) next »