3

When working with the singleton pattern. Is there any difference when holding the static instance in the class and holding it in the method that returns the instance?

Examples: Inside the class.

class cExampleA {
    static $mInstance;

    protected function __construct() {
        /* Protected so only the class can instantiate. */
    }

    static public function GetInstance() {
        return (is_object(self::$mInstance) ? self::$mInstance : self::$mInstance = new self());
    }
}

Inside the returning method.

class cExampleB {
    protected function __construct() {
        /* Protected so only the class can instantiate. */
    }

    static public function GetInstance() {
        static $smInstance;
        return (is_object($smInstance) ? $smInstance : $smInstance = new self());
    }
}

On a side note, the use of a ternary operator valid in the example (meaning could it cause problems) and is there any benefit/downfall to using is_object over isset?

Update: It seems that the only difference is that scope of the static instance?

James
  • 2,609
  • 3
  • 20
  • 27
  • the main thing that jumps out at me here is that in exampleA, the static property is publically accessible. I'm guessing this isn't what you want, so you should probably make it `private` (especially as you're only checking it with `is_object()`, which means it could be overwritten with anything. `instanceof self` would be safer). – SDC Feb 04 '13 at 14:31
  • Yes I just missed off private. instanceof sounds like a good idea, I always forget about it. – James Feb 04 '13 at 14:41
  • I have to be honest, I don't know that there is a difference in this case. I guess it's one of those cases where there's more than one way to achieve the same thing. Unless someone can show me a reason otherwise. For me, I'll stick with using the private property (ie exampleA), but I can't see any reason why exampleB is wrong. – SDC Feb 04 '13 at 16:00
  • I guess you could argue that declaring the `private static $mInstance = NULL;` at the top of the class (as per example A) is more readable too (especially if you had lots of static variables in a class). I'm also not sure your IDE would be able to code complete inside other functions if the variable is declared as per example B. I can't see any other fundamental difference though, but I would use example A. :) – Tom Feb 04 '13 at 16:29

2 Answers2

1

Interesting question. In terms of behaviour, as far as I'm aware there is no difference at all between the two examples (other than scope).

PHP is a loosely typed programming language, so you could even omit the class property declaration all together in Example A. And with a loosely typed language there always seems to be more ways of achieving the same thing!

The real issue then soon becomes one of design pattern (data encapsulation in this case) to ensure we're writing code that follows a convention devised by people far smarter that I!

In this example, the Class should own its property and set the scope of that property appropriately (private in this case) and provide logical accessor methods.

Here's how I would write it:

class ExampleA
{
    static private $_instance = null;

    private function __construct(){}

    static public function getInstance()
    {
        if (!self::$_instance instanceof self) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}

If you were to enclose the variable within the method itself, strictly speaking it wouldn't be a class property. Also, you lose a bit a legibility is a sense that other developers (not used to the design pattern of Example B) would be looking for a class property declaration, rather that digging through class methods.

Community
  • 1
  • 1
jmat
  • 320
  • 2
  • 10
  • Thanks for your input. I understand your point of view from a readability point of view but there doesn't seem to be any technical points to your argument. On a side note, I'm not using Hungarian Notation the prefixes relate to scope not to variable type. – James Apr 08 '13 at 11:36
0

Is there any difference when holding the static instance in the class and holding it in the method that returns the instance?

No, there's no difference in functionality, granted you modify the visibility of the static instance property to either protected or private:

class cExampleA {
    protected static $instance = null;
    // ...
}

Btw, don't use notations like $mInstance; nowadays you don't need those crutches

Also, seeing how you set the constructor to protected visibility, I'm assuming that you want to be able to extend the class later? In that case, you would need to change the getInstance() method:

public final static function GetInstance() 
{
    if (self::$instance === null) {
        self::$instance = new static;
    }
    return self::$instance;
}

Otherwise, your constructor should simply be private so that you can use new self; again.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • I've never seen 'new static' used before. Often when I want to extend the class I've used different approaches depending on how the instance or instances are going to be used. On a side note, I often get comments about my coding style. It isn't Hungarian notation as most people presume but instead an indicator of scope to prevent naming collisions. – James Apr 08 '13 at 11:42
  • @James yep it's late static binding :) – Ja͢ck Apr 08 '13 at 12:08