Show on your fingers what is Singleton for ?

class Singleton { protected static $instance; // object instance /** * Защищаем от создания через new Singleton * * @return Singleton */ private function __construct() { /* ... */ } /** * Защищаем от создания через клонирование * * @return Singleton */ private function __clone() { /* ... */ } /** * Защищаем от создания через unserialize * * @return Singleton */ private function __wakeup() { /* ... */ } /** * Возвращает единственный экземпляр класса * * @return Singleton */ public static function getInstance() { if ( is_null(self::$instance) ) { self::$instance = new Singleton; } return self::$instance; } public function doAction() { /* ... */ } } //usage Singleton::getInstance()->doAction(); 

Why write so? If you can write like this:

 class Singleton { public static function doAction() { /* ... */ } } Singleton::doAction(); 

Not easier, no? %)

Just do not give links to Wikipedia, etc.


Thanks to all! @knes , @ikoolik and @ Nord001 - I threw 25 points for your effort.

  • ran into the background of this issue. @AlexWindHope, we are waiting for you with impatience. - ikoolik
  • @ikoolik, yes, we are waiting. - Oleg
  • @knes has already painted everything remarkably, the difference between the presence of an instance and its complete absence, on the fingers, wrote @ikoolik in the comments to his answer. What more do you need? I already wrote, if after that it is not clear - it means that they have not grown up, the essence itself is beautifully described in Wikipedia +, now, it is cracked here. - Zowie
  • and what, the article will not be? = ( - ikoolik
  • Imagine =) - Zowie

5 answers 5

A singleton is needed to know for sure that we have ONE object of this class created. A classic example is a connection to a database.

If a bunch of scripts inside a single file pulls the database in different functions, you have to set up a global connection variable and constantly check whether it is alive, in case the first connection to the database is in progress.

Singleton creates the connection itself, if it has not yet been established, or simply returns the finished link. You only need to call him, no longer worrying about anything: they will not disturb the base once again.

Your second example is bad because you can create a bunch of objects of this class that will not know what is happening with the rest.

  • In short, I understood. That is, if the __construct() function is used, then each time db::select() is called will __construct() be called? - Oleg
  • Not. A constructor in a singleton is called once for the entire lifetime of the script. - knes
  • I do not understand in general. - Oleg
  • @exec, the singleton constructor is private, that is, the object cannot be created outside. And when you call the getInstance function, it is checked whether an instance already exists, if not, it is created. From this it turns out that only one instance of an object can exist in principle. Although you asked without references, it is better to read good authors: Myers, Alexandrescu. Or at least habr - northerner
  • one
    Bad example IMHO. In real portals - there is a lot of connections to different databases. Yes, and in general, the singleton is really the same as the static — the only thing that is bad if the beginner starts a static class to instantiate, and push non-static properties / methods there: but only beginners can do it. And if a couple of static methods appear in the singleton with the hands of the same beginner - nothing terrible will happen. - Goncharov Alexander

Singleton is one of the easiest, but at the same time extremely significant design patterns. For what it is, has already been answered. The main implementation is shown by you, but everyone can screw their own ones. So, for example, in C ++ you can create a separate template class Singleton using the template<type> method, and then you can make a singleton from any existing class.

    Above wrote about a DB, I so:

    Singleton :: getInstance ('main') -> doAction ();

    Singleton :: getInstance ('no_main') -> doAction ();

    I will explain. There are 3 sites. 4 DB. Of these, 3 databases are databases with information from a specific site, and the fourth database is user data, since on all 3 sites they are the same. So when I need to make a request to the user database, I use:

    Singleton :: getInstance ('main') -> doAction ();

    if we suppose we need articles, then:

    Singleton :: getInstance ('no_main') -> doAction ();

    Thus, I am guaranteed to have no more than 1 connection to a specific database.

    In fact, you can do as you wrote:

    Singleton :: doAction ();

    But if you need any data, you will still call> getInstance () in order to apply to the database.

      The fact is that the singleton allows you to create only one of its own copy.

      Accordingly, all classes in which a singleton object is used use the same object. With the same data.

      Let's take an example from the answer of comrade @knes about connecting to the database. If the database connection is entered into the singleton constructor, then all classes using the database through the singleton use the same connection.

      Another example:

       *** тут обьявление обычного класса `MyClass` с `private $a` и `getA(), setA()` *** $class1 = new MyClass(); $class2 = new MyClass(); $class2->setA(3); $class1->setA(5); echo $class2->getA(); //3 

      Same if myClass is singleton:

       $class1 = myClass::getInstance(); $class2 = myClass::getInstance(); $class2->setA(3); $class1->setA(5); echo $class2->getA(); //5 

      All of the above is only the most understandable illustration of the mechanism in my opinion. The advantages and disadvantages of a singleton is another story.

      • > Another example: Add an arbitrary variable to a singleton. Then add geter and seter for it. It's simple. The trick is that we can specify the value of this variable in one class, and get in another WITHOUT transferring a singleton object between classes. It works for me without singleton. - Oleg
       class Singleton { private static $PrS='init private'; public static $PuS='init public'; public static function PrS($A=false) { if($A!==false) self::$PrS=$A; else return self::$PrS; } public static function PuS($A=false) { if($A!==false) self::$PuS=$A; else return self::$PuS; } } echo Singleton::PrS(); echo "\n"; echo Singleton::PuS(); // выведет init private // init public echo "\n -- \n"; $D = new Singleton(); echo $D->PrS(); // также выведет init private echo "\n"; // init public echo $D->PuS(); echo "\n -- \n SET them all!"; // А вот здесь Singleton::PrS('changed private'); // меняем переменные класса Singleton::PuS('changed public'); // используя статическую ссылку echo "\n"; // и попробуем проверить их из "созданного" класса (хотя это просто ссылка копия) echo $D->PrS(); // разумеется, выведет: changed private echo "\n"; echo $D->PuS(); // changed public 

      Copy this simple example, run it, and you will understand that the static class, together with its static variables, is not duplicated by the new operator. Yes, at least ten duplicates do it - all the same - static variables will remain.

      The word static for the function indicates that the address in the global table when it is compiled is already allocated - it is strictly allocated. Similarly with static variables - their address is also static. And nonstatic variables (classes) do not exist in the address space until they are defined (by the operator new). There is nowhere to turn. For static, the address is already there - and you can always access it (the variable) - someStaticClass :: value

      If you want to use a static class for working with a database, get a private static variable DB_handler inside. It is necessary to work with several connections (several databases) - get it as needed. You can even build something of a static array. Why not? You will need to dodge too much - rewrite the class. Those. copies of static classes do not differ at all (when they are made by the operator new), until at least one non-static variable appears in them. True, after that they will differ only in this non-static variable. True, at the same time, to manage this variable is already obtained only from the manufactured class.

      Further:

       public static function getInstance() { if ( is_null(self::$instance) ) { self::$instance = new Singleton; } return self::$instance; } 

      This is just a piece of code that returns a copy of the link to the address of the static class Singleton. This is the same as writing Singleton: :( and there is something)

      That is what the question was about - "WHY?". The answer is simple - yes, nothing. :)

      Probably, there are tasks where you need to make a copy of the class Singleton, " ... but if there were no appeals (well, something was not needed), then nothing will start and everything will be quiet and calm ... But it seems like a static class will exist even when it may not be needed ... and oh, how terrible will it be to eat memory ... "In general, somehow I cannot come up with such a task right now to apply the CREATION of classes instead of static classes.

      And here, for example, I also don’t see the difference between complex Singleton and simple Singleton :: doAction (). In general, static classes (with static variables) are also extremely convenient because they provide "global" variables for any area of ​​visibility. And the handler for the database is a vivid example.

      • Aha, only not asil - if static methods are so convenient, then why bother with OOP? For namespaces? So they are in PHP and so it is. You just, like the TS, do not quite understand why OOP is needed - Zowie
      • This is the same as writing Singleton:: (and there is something there) Oh? .. If there was no need, you wouldn’t use it, moreover, it wouldn’t exist, then you don’t understand your problem, no pattern at all - Zowie
      • In general, I do not need it. I have all static classes and variables in them too. - Oleg
      • Then you don't need OOP at all - Zowie
      • 2
        @Cooleronline, by your logic, it turns out that OOP is also not needed, because everything can be rewritten procedurally. Having received a link to a singleton instance, you can pass it by the parameter of other methods to build interfaces. This fundamentally distinguishes the singleton from the "pure static" class. Also a good analysis can be found here . - northerner