note 99446 added to language.oop5.patterns
| From: | boukeversteegh at gmail dot com | 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