Andreev index php user. Global array $_SERVER in PHP
The article will be useful primarily to developers who get lost during interviews when they hear the question “What are the main differences between a singleton and a static class, and when should one be used and when the other?” And it will certainly be useful for those developers who, when they hear the word “pattern,” become despondent or ask to stop expressing themselves :)
What is a static class?
First, let's remember what a static class is and why it is needed. Any CLI-compatible language uses the following global variable encapsulation paradigm: no global variables. All members, including static ones, can only be declared within a class, and the classes themselves can ( but they shouldn't) be grouped in some namespace. And while previously you had to imitate the behavior of a static class using a private constructor, the .NET Framework 2.0 added support for static classes at the platform level. The main difference between a static class and a regular, non-static one is that it is impossible to create an instance of this class using the operator new. Static classes are essentially a kind of namespace - only, unlike the latter, they are designed to house static variables and methods rather than types.What is Singleton?
One of generating patterns first described by the Gang of Four (GoF). Ensures that the class has only one copy, and provides it with global access point. We will not consider this pattern in detail here, its purpose and the tasks it solves - there is a lot of detailed information about it on the Internet (for example and). I’ll just note that singletons can be thread-safe or not, with simple and lazy initialization.And if there is no difference, why produce more?
So what exactly is the difference between these two entities and when should you use them? I think this is best illustrated in the following table:Singleton |
Static class |
|
---|---|---|
Number of access points
|
One (and only one) access point - static field Instance |
N (depends on the number of public class members and methods) |
Class inheritance
|
Possibly, but not always (more on this below) |
Impossible - static classes cannot be instantiated because objects of static classes cannot be instantiated |
Interface inheritance
|
Possibly without any restrictions |
|
Possibility of passing as parameters
|
Possibly since Singleton provides real object |
Absent |
Controlling the lifetime of an object
|
Perhaps - for example, lazy initialization(or creation on demand) |
Impossible for the same reason class inheritance is impossible |
Using an abstract factory to instantiate a class
|
Maybe |
Impossible due to the lack of the ability to create an instance |
Serialization
|
Maybe |
Not applicable due to lack of copy |
Let's take a closer look at the criteria listed above.
Number of access points
Of course we mean external access points, in other words, a public contract for the interaction of a class and its clients. It's easier to illustrate this with code:Singleton in the "canonical" implementation:
public class Session ( private static Session _instance; // Pattern implementation... public static Session Instance ( get ( // ... return _instance; ) ) public IUser GetUser() ( // ... ) public bool IsSessionExpired() ( // ... ) public Guid SessionID ( get ( // ... ) ) )
Static class:
public static class Session ( // Access Point 1 public static IUser GetUser() ( // ... ) // Access Point 2 public static bool IsSessionExpired() ( // ... ) // ... // Access Point N public static Guid SessionID ( get ( // ... ) ) )
Class inheritance
With inheritance of static classes, everything is simple - it is simply not supported at the language level. With Singleton things are a little more complicated. For ease of use, many developers most often use the following implementation of the pattern:public class Singleton
And since multiple inheritance is prohibited in C# and in any CLI-compatible language, this means that we cannot inherit the Session class from any other useful class. The solution is to delegate access control to the object instance to the singleton:
public class Session: CoreObject ( private Session() ( ) public static Session Instance ( get ( return Singleton
Interface inheritance
Using interfaces allows you to achieve greater flexibility, increase the amount of reusable code, increase testability, and, most importantly, avoid strong connectivity objects. Static classes do not support inheritance at all. Singleton, on the contrary, fully supports interface inheritance, since it is a regular class. But this feature should be used only if the singleton instance is planned to be passed as input parameters in mixed scenarios or broadcast across domain boundaries. Mixed scenario example:// This class is a Singleton and implements the ISession interface public class Session: CoreObject, ISession ( private Session() ( ) public static Session Instance ( get ( return Singleton
Possibility of passing as parameters
This is not supported for static classes - you can only pass the type, but in most situations this is useless, except when using reflection mechanisms ( reflection). A singleton is essentially an ordinary instance of an object:// ... ISessionManager _sessionManager; // ... bool isExpired = _sessionManager.IsSessionExpired(Session.Instance);
Controlling the lifetime of an object
The lifetime of a static class is limited by the lifetime of the domain - if we created this domain manually, then we indirectly control the lifetime of all its static types. We can control the singleton's lifetime as we wish. A striking example is lazy initialization:public class Singleton
You can also add an operation to remove a singleton instance:
public class Singleton
This operation is extremely unsafe because the singleton may store some state and therefore its re-creation may have undesirable consequences for its clients. If, nevertheless, the need for such a method arose (which most likely indicates design errors), then you should try to minimize the possible harm from its use - for example, make it private and call it inside the Instance property under certain conditions:
public class Singleton
Using an abstract factory to instantiate a class
A static class does not support this feature due to the fact that an instance of a static class cannot be created. In the case of a singleton, everything looks simple:public interface IAbstractFactory ( T Create
True, in the version with singleton aggregation, you will have to use a not very beautiful and slightly cumbersome solution:
public class Session: CoreObject, ISession ( private class SessionSingleton: Singleton
Serialization
Serialization only applies to instances of classes. A static class cannot have instances, so there is nothing to serialize in this case.So should you use Singleton or Static class?
In any case, the choice of solution depends on the developer and the specifics of the problem he is solving. But, in any case, the following conclusions can be drawn:Using a singleton is justified when:
- It is necessary to inherit classes or interfaces or delegate the construction of objects to a factory
- Requires class instances
- It is necessary to control the lifetime of an object (although this is a very rare task for a singleton)
- It is necessary to serialize an object (this task is hypothetically possible, but it is difficult to imagine use cases)
Today I want to sort it out singleton design pattern, which is very often used in object-oriented programming.
Single Design Pattern or Pattern Singleton is needed so that we do not have many objects of the same type, but only one is always used. An example is a class for working with a database.
ClassDB(
protected $db;
Public function __construct() (
$this->
}
Public function get() ()
public function set()
public function del() ()
}
$db1 = new DB();
$db2 = new DB();
We already have 2 object $db1 And $db2, and then someone, not knowing that such an object already exists, will create a third one, etc. This has a very bad effect on the performance and readability of the code, and in our case it may crash, because Hosting has a limited number of database connections.
It was invented to solve this problem singleton pattern.
ClassDB(
protected $db;
static private $instance = null;
Private function __construct() (
$this->db = new Mysqli($host, $user, $pass, $database);
}
Private function __clone() ()
Static function getInstance() (
if(self::$instance == null) (
self::$instance = new self();
}
return self::$instance;
}
}
$db = new DB(); // error
$db = DB::getInstance();
$db2 = DB::getInstance();
$db3 = DB::getInstance();
To make it impossible to create an object in the usual way, we make our constructor private, but also don’t forget that objects can clone and also close the method __clone. Next we create a static property $instance, which by default is null. Now let's create a static method getInstance() which checks if our static property is equal to null? If yes, then we create an instance of our object and return it, and if not, then we simply return it. This way, we will always have the same instance, no matter how many times we create them. Using it is very simple: assign a variable the value that is returned by the static method getInstance(), class D.B., and then we work as with a regular object.
Today I’ll tell you about the Singleton design pattern. Target: create a class that will have only ONE object. This means that no matter how many times it is accessed, the same object that was created the first time will be returned. This is a convenient thing and necessary in many places, it’s not for nothing that it is being implemented into frameworks. Application:- For example, you need to connect a database to a project and a class that will be responsible for connecting to it. The connection is created once and there is no need to create it again and again
- Application settings - a class responsible for the settings required for the application: database host and port, etc. They are created once and used throughout the application's operation.
- There are many more examples that I haven’t mentioned, so write your options in the comments! =)