I am currently trying to figure out what the best way is to create my objects on my current PHP 5.2 project. I basicly have a Registry which returns objects by keys. If the Registry does not have an object with the specified key it will try to create one by calling a factory method that is supplied to the registry by construction. Look at the following code to calrify:
interface IFactory
{
public function createProduct( $key );
}
class Registry
{
private $m_elements = array( );
private $m_factory;
public function __construct( IFactory $factory )
{
$this->m_factory = $factory;
}
public function getElement( $key )
{
if ( !array_key_exists( $key, $this->m_elements ) )
{
$this->m_elements[$key] = $this->m_factory->createProduct( $key );
}
return $this->m_elements[$key];
}
}
Because I have different of categories of objects I'd like to store in different registries I wrap a Registry oject into a singleton for each category, like this:
class SpecialRegistry
{
private static $instance = null;
public static function getInstance( )
{
if( self::$instance === null )
{
self::$instance = new Registry( new SpecialFactory( ) );
}
return self::$instance;
}
}
My Special class is rather complex and big with alot of different attributes and composition objects. Because I do not want to bind my Special class to any specific backend I was going to have different Factories for each different backend (eg MySQL database or file stream). So I would move the loading and initialization logic to the Factories. This however will only work if all fields in the Special class are public to the Factory. They shouldn't however be public to the rest of the application.
In C++ I could use friends to circumvent this problem. Also here on stack overflow I read on nearly the same topic, but applied to C#. It said I should simply set all fields public in the Special class and have the Factory only return an Interface that exposes the methods and attributes I want to be public to the application. But since PHP does not support return type hinting I am not able to return only an interface that the Special class implements. Another way I came up with would be to actually have the SpecialFactory inherit from the Special class making it possible to access private and protected fields from the factory. This is what I called "Bastard Factory" since the factory inherits from it's own product.
I'd wish to know if anyone of you guys can come up with a better way of achieving what I want. Or am I completely off track and yielding the initialization process to the factory is an absolute no-go? I'm curious on your opinions!