This is actually an interesting question, and there's an easy (but ugly) fix to it (see below).
So I'm asking if there's a better way to do it.
What I'd like to do is making an object constructor return something else rather than a new instance.
Here's an example of what I'm trying to achieve:
$GLOBALS['object_cache']=array();
class Test {
public function __construct($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$GLOBALS['object_cache'][$id]=$this;
}
}
$t0=new Test(0);
$t1=new Test(1);
$t01=new Test(0);
// modifying $t01 would presumably also modify $t0
The easy (but ugly?) fix:
$GLOBALS['object_cache']=array();
class Test {
public static function create($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$new=new Test();
$GLOBALS['object_cache'][$id]=$new;
return $new;
}
}
$t0=Test::create(0);
$t1=Test::create(1);
$t01=Test::create(0);
// modifying $t01 would presumably also modify $t0
What do you guys think? Example 1 doesn't work, by the way; it returns a new instance regardless of the return statement.
So am I missing something, or is the better way the second one?
PS: No need stating the obvious about patterns (factory/singleton)...
You could also use a procedural version:
class Test {
function __construct($i) {}
}
function Test($i) {
static $cache;
if (isset($cache[$i])) {
return $cache[$i];
}
else {
return $cache[$i] = new Test($i);
}
}
It's slightly nicer on the eyes, and allows for e.g. instant fluent Test(1)->do()->else()
calls.
ps: Store the instances in static
class variable and second solution will not be so weird like now.
Basically what you're trying to do is implementing a Singleton pattern combined with a Factory method pattern. Anyone should be able to tell how it works if you document it in your technical documentation (and in your comments), so the first way can be used.
The second solution actually seems less obvious to me.