cakyus
cakyus

Reputation: 854

Extending a singleton class

i used to create an instance of a singleton class like this:

$Singleton = SingletonClassName::GetInstance();

and for non singleton class:

$NonSingleton = new NonSingletonClassName;

i think we should not differentiate how we create an instance of a class whether this is a singleton or not. if i look in perception of other class, i don't care whether the class we need a singleton class or not. so, i still not comfortable with how php treat a singleton class. i think and i always want to write:

$Singleton = new SingletonClassName;

just another non singleton class, is there a solution to this problem ?

Upvotes: 5

Views: 2669

Answers (5)

TheWebGuy
TheWebGuy

Reputation: 31

I know this is a really old post, but i understood Factory pattern better with the help of the below link.

So if it helps an future wandered. . . . here goes

http://www.devshed.com/c/a/PHP/Design-Patterns-in-PHP-Factory-Method-and-Abstract-Factory/1/

It was very simple to grasp and understand the basic implementation.

Upvotes: 1

Yacoby
Yacoby

Reputation: 55445

I wouldn't recommend it as it would make your code a lot harder to understand (People think new means an entirely new object). But then I wouldn't recoemmed the use of Singletons.

The basic idea of this code is that there is a wrapper around a singleton. All functions and variables accessed through that wrapper actually effect the singleton. It isn't perfect as the code below doesn't implement a lot of magic methods and SPL interfaces but they can be added in if required

Code

/**
 * Superclass for a wrapper around a singleton implementation
 *
 * This class provides all the required functionality and avoids having to copy and
 * paste code for multiple singletons.
 */
class SingletonWrapper{
    private $_instance;
    /**
     * Ensures only derived classes can be constructed
     *
     * @param string $c The name of the singleton implementation class
     */
    protected function __construct($c){
        $this->_instance = &call_user_func(array($c, 'getInstance'));
    }
    public function __call($name, $args){
        call_user_func_array(array($this->_instance, $name), $args);
    }
    public function __get($name){
        return $this->_instance->{$name};
    }
    public function __set($name, $value){
        $this->_instance->{$name} = $value;
    }
}

/**
 * A test singleton implementation. This shouldn't be constructed and getInstance shouldn't
 * be used except by the MySingleton wrapper class.
 */
class MySingletonImpl{
    private static $instance = null;
    public function &getInstance(){
        if ( self::$instance === null ){
            self::$instance = new self();
        }
        return self::$instance;
    }

    //test functions
    public $foo = 1;
    public function bar(){
        static $var = 1;
        echo $var++;
    }
}

/**
 * A wrapper around the MySingletonImpl class
 */
class MySingleton extends SingletonWrapper{
    public function __construct(){
        parent::__construct('MySingletonImpl');
    }
}

Examples

$s1 = new MySingleton();
echo $s1->foo; //1
$s1->foo = 2;

$s2 = new MySingleton();
echo $s2->foo; //2

$s1->bar(); //1
$s2->bar(); //2

Upvotes: 2

zerkms
zerkms

Reputation: 254896

Based on what new keyword means all you want is irrelevant. new creates new instance of class, thats why it named new :-)

Upvotes: 1

Gordon
Gordon

Reputation: 316969

You cannot create a Singleton the same way as a regular class instance. new will always return a new instance, thus you have to have the constructor non-public and thus you have to have a different means to call it from within the class.

You could have factory methods on all classes, e.g. always do getInstance() like shown in another answer. Another option would be to use a Service Locator and Dependency Injection Framework that knows whether to return what.

Upvotes: 1

Bozho
Bozho

Reputation: 597046

It better be the other way around - provide a factory-method for non-singletons, and get instances of them using:

$NonSingleton = NonSingletonClassName::createInstance();

This is a recommended best practice for Java (in Effective Java), but it applies to most object-oriented languages.

Upvotes: 3

Related Questions