Anyway, I started tinkering with the concept of using a ServiceLocator class to manage and cache all those Singletons, push them into a single access point, and allow the ServiceLocator to be responsible for locating the class file, instantiating the object, caching it, and returning the new/cached copy. Whew! Anyways, the class so far...
Code: Select all
class Partholan_ServiceLocator /* implements Partholan_iServiceLocator */ {
private static $instance = false;
private $instances = array();
private $factories = array();
private $searchLocations = array();
public function __construct() { // allow direct instances
}
static function getInstance() {
if(!self::$instance)
{
self::$instance = new Partholan_ServiceLocator();
}
return self::$instance;
}
public function registerService($serviceName, $serviceInstance) {
if(is_object($serviceInstance) && strlen($serviceName))
{
$this->instances[$serviceName] = $serviceInstance;
return true;
}
trigger_error('Service could not be registered. Requires a valid Service name and object.');
}
public function removeService($serviceName) {
unset($this->instances[$serviceName]);
}
public function getService($serviceName) {
if(isset($this->instances[$serviceName]))
{
return $this->instances[$serviceName];
}
elseif(is_class($serviceName))
{
$this->instances[$serviceName] = new $serviceName();
return $this->instances[$serviceName];
}
else
{
foreach($this->searchLocations as $location)
{
if(file_exists($location . DIRECTORY_SEPARATOR . $serviceName . '.php'))
{
require_once($location . DIRECTORY_SEPARATOR . $serviceName . '.php');
$this->instances[$serviceName] = new $serviceName();
return $this->instances[$serviceName];
}
}
}
// factory lookups to be added later
trigger_error('Specified Service could not be located.', E_USER_ERROR);
}
public function registerFactory($factoryName, $serviceFactory) {
if(is_object($serviceFactory) && strlen($factoryName))
{
$this->factories[$factoryName] = $serviceFactory;
return true;
}
trigger_error('Factory could not be registered. Requires a valid Factory name and object.');
}
public function addSearchLocations() {
foreach(func_get_args() as $dirPath)
{
$this->searchLocations[] = $dirPath;
}
}
public function hasService($serviceName) {
if($this->instances[$serviceName])
{
return true;
}
return false;
}
public function hasFactory($factoryName) {
if($this->factories[$factoryName])
{
return true;
}
return false;
}
public function hasSearchLocation($dirPath) {
if(in_array($dirPath, $this->searchLocations))
{
return true;
}
return false;
}
}Code: Select all
class EmptyObject {
public function __construct() {}
}Code: Select all
class Partholan_ServiceLocator_TestCase extends UnitTestCase {
public function __construct() {
$this->UnitTestCase();
}
public function setUp() { }
public function tearDown() { }
public function testRegisteringService() {
$sl = new Partholan_ServiceLocator();
$sl->registerService('EmptyObject', new EmptyObject);
$this->assertTrue($sl->hasService('EmptyObject'));
$this->assertIsA($sl->getService('EmptyObject'), 'EmptyObject');
}
public function testRemovingService() {
$sl = new Partholan_ServiceLocator();
$sl->registerService('EmptyObject', new EmptyObject);
$sl->removeService('EmptyObject');
$this->assertFalse($sl->hasService('EmptyObject'));
}
public function testAddingSearchLocations {
$sl = new Partholan_ServiceLocator();
$sl->addSearchLocations('/tmp', '/home');
$this->assertTrue($sl->hasSearchLocation('/tmp'));
$this->assertTrue($sl->hasSearchLocation('/home'));
}
// test: no class, no file included - get file and instantiate object
public function testGettingServiceInstanceFromFile() {
$sl = new Partholan_ServiceLocator();
$sl->setSearchLocations(dirname(__FILE__)); // or location of EmptyObject.php if other
$mk = $sl->getService('EmptyObject');
$this->assertIsA($mk, 'EmptyObject');
$this->assertTrue($sl->hasService('EmptyObject'));
}
// test: is_class method where file pre-included()
public function testGettingServiceInstance() {
$sl = new Partholan_ServiceLocator();
$mk = $sl->getService('EmptyObject');
$this->assertIsA($mk, 'EmptyObject');
$this->assertTrue($sl->hasService('EmptyObject'));
}
public function testRegisteringFactory() {
$sl = new Partholan_ServiceLocator();
$sl->registerFactory('EmptyObject', new EmptyObject);
$this->assertTrue($sl->hasFactory('EmptyObject'));
$this->assertIsA($sl->getFactory('EmptyObject'), 'EmptyObject');
}
}