views:

97

answers:

4

I have a singleton factory and would like it to return a reference to the object instance so that I can use the singleton factory to destroy the instance and not have instances elsewhere in my code to survive.

Example of what I would like to be able to do:

$cat = CatFactory::getInstance();
$cat->talk(); //echos 'meow'
CatFactory::destructInstance();
$cat->talk(); //Error: Instance no longer exists
+2  A: 

Based on the documentation for unset, I do not think that is possible. You cannot actually destroy an object, only a handle to it. If other variables are around that still hold a reference, the object will continue to live on.

Aistina
A: 

You can accomplish what you want by having your Cat object enforce a private $destroyed property. PHP 5 passes objects by reference by default, so you don't have to worry about that part.

bluej100
A: 

A work around would be creating a cat class

class cat
{
  public $cat;

  public function __construct()
  {
    $this->cat = CatFactory::getInstance();
  }

  public function __destruct()
  {
    CatFactory::destructInstance();
  }

}

$cat = new cat();
$cat->cat->talk();
$cat->cat->talk();
streetparade
... I don't get it.
Aistina
+2  A: 

This could work:

<?php
class FooFactory
{
  private static $foo;

  private function __construct()
  {
  }

  public static function getInstance()
  {
    return self::$foo ? self::$foo : (self::$foo = new FooFactory());
  }

  public static function destroyInstance()
  {
    self::$foo = null;
  }

  public function __call($fn, $args)
  {
    if (!method_exists(self::$foo, $fn) || $fn[0] == "_")
      throw new BadMethodCallException("not callable");

    call_user_func_array(array(self::$foo, $fn), $args);
  }

  # function hidden since it starts with an underscore
  private function _listen()
  {
  }

  # private function turned public by __call
  private function speak($who, $what)
  {
    echo "$who said, '$what'\n";
  }

}

$foo = FooFactory::getInstance();
$foo->speak("cat", "meow");
$foo->_listen();                 # won't work, private function
FooFactory::destroyInstance();
$foo->speak("cow", "moo");       # won't work, instance destroyed
?>

Obviously it is a hack.

konforce
I'm struggling to understand how this works. Could you elaborate for me please?
Pheter
By marking the methods as private, it triggers the magical `__call` method. That function essentially just forwards the call on to the private function if the `private static $instance` hasn't been destroyed.It is sort of the same thing as adding `if (!self::$instance) throw new Exception();` at the top of every public function.
konforce