I made a code that seems to mix Singleton design pattern, and Fatory method. But my factory method is in an abstract class inherited by my Singleton ... what the hell have I created ? Does it have a name ?
Here is the situation (in PHP I hope to be understandable by everyone) :
I had a circular inclusion problem :
class ThingsService {
private $stuff_service ;
public function __construct () {
$this->stuff_service = new StuffService () ;
}
public function f () { $this->stuff_service->f() ; }
public function g () { echo "Hello world !\n" ; }
}
class StuffService {
private $things_service ;
public function __construct () {
$this->things_service = new ThingsService () ;
}
public function f () { $this->things_service->g() ; }
}
$toto = new ThingsService () ;
$toto->f() ;
Creating a ThingsService
lead to creating a StuffService
which lead to creating a ThingsService
... and so on.
Due to time development constraints, it wasn't possible to change the codes of f
and g
methods. Due to how my code works, it was possible to implement StuffService
and ThingsService
as Singletons. Due to the fact that they were both "Services", it was possible to factorize some code with some inheritance. Hence, I did this :
abstract class Service
{
private static $_instances = [];
public static function get_instance ()
{
$required_class = get_called_class () ; // "StuffService" or "ThingsService"
if (!isset (self::$_instances[$required_class]))
{
new static () ;
}
return self::$_instances[$required_class] ;
}
protected function __construct ()
{
$required_class = get_called_class () ;
self::$_instances[$required_class] = $this ;
}
}
class ThingsService extends Service
{
private $stuff_service ;
protected function __construct ()
{
parent::__construct () ;
$this->stuff_service = StuffService::get_instance () ;
}
public function f () { $this->stuff_service->f() ; }
public function g () { echo "Hello world !\n" ; }
}
class StuffService extends Service
{
private $things_service ;
protected function __construct ()
{
parent::__construct () ;
$this->things_service = ThingsService ::get_instance () ;
}
public function f () { $this->things_service->g() ; }
}
$toto = ThingsService::get_instance () ;
$toto->f() ;
Edit due to subsequent answers
In the actual code, there are more than 2 XxxxxService
class: there are actually 15 of them, each containing between 500 and 2000 lines of code. This interdependency is the result of a not well thought out architecture that wasn't good enough to support the recent augmentation of the code size. It is not possible to merge them in one file due to this huge amount of lines.
As I told earlier, this new architecture is also constrained by the time we can invest in this refactoring (refactoring 15 constructor is possible, but changing 235 method calls everywhere in the code isn't likable).
So my questions are:
- Is this a known design pattern ?
- If yes, does it have a name ?
- Does this code design seems ok to you ? Or do you think it's a dirty or problematic code (and why) ?