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 where T: class ( private static T _instance; protected Singleton() ( ) private static T CreateInstance() ( ConstructorInfo cInfo = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type, new ParameterModifier); return (T)cInfo.Invoke(null); ) public static T Instance ( get ( if (_instance == null) ( _instance = CreateInstance(); ) return _instance; ) ) public class Session: Singleton ( public IUser GetUser() ( // ... ) public bool IsSessionExpired() ( // ... ) public Guid SessionID ( get ( // ... ) ) )
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 .Instance; ) ) )
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 .Instance; ) ) ) // This class is not a singleton and can generally be declared and implemented in another assembly // completely hiding the implementation details public class VpnSession: ISession ( ) public interface ISessionManager ( ISession GetSession(Guid sessionID); // Accepts the ISession interface, following the principles of reducing coupling bool IsSessionExpired(ISession session);
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 where T: class ( // ... public static T Instance ( get ( if (_instance == null) ( // Create "on demand" _instance = CreateInstance(); ) return _instance; ) ) )
You can also add an operation to remove a singleton instance:
public class Singleton where T: class ( // ... public static T Instance ( // ... ) // A very dangerous operation! public void RemoveInstance() ( _instance = null; ) )
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 where T: class ( // ... public static T Instance ( get ( if (!IsAlive) ( // Removal by condition RemoveInstance(); ) if (_instance == null) ( // Creation "on demand" _instance = CreateInstance(); ) return _instance; ) ) private void RemoveInstance() ( _instance = null; ) )
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 (); bool IsSupported (); ) public class Singleton where T: class ( private static T _instance; private static IAbstractFactory _factory; protected Singleton(IAbstractFactory factory) ( _factory = factory; ) public static T Instance ( get ( if (_instance == null) ( _instance = _factory.Create (); ) return _instance; ) ) ) // Option with direct inheritance from Singleton public class Session: Singleton ( protected Session() : base(new ConcreteFactory()) ( ) // ... )
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 ( protected SessionSingleton() : base(new ConcreteFactory2()) ( ) ) private Session() : base(new CoreContext()) ( ) public static Session Instance ( get ( return SessionSingleton.Instance; ) ) // ... )
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)
Using static classes is advisable then when you don't need to implement any of the scenarios listed for the singleton. The main purpose of static classes is to group logically similar methods, constants, fields and properties. For example: System.Math, System.BitConverter, System.Buffer, System.Convert etc.

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! =)
After this introduction, as I understand it, we can show an example of this class: (Although I am sure that each of us can come up with an implementation of this) Here is the simplest example, when we make the constructor private, i.e. You cannot create an object explicitly. And there is a static method getInstance() that provides the object. public class Singleton ( private static Singleton instance; private Singleton () ( ) public static Singleton getInstance () ( if (instance == null) ( instance = new Singleton () ; ) return instance; ) ) There are problems with multithreading and then you can put the getInstance() method synchronized marker: public class Singleton ( private static Singleton instance; private Singleton () ( ) public static synchronized Singleton getInstance () ( if (instance == null) ( instance = new Singleton () ; ) return instance; ) ) In the end, as usual, I want to say that if you think differently or find a mistake in me - write in the comments! We will discuss everything with pleasure :) If you liked the article, write “+” and I will know it. This is important to me :) P.S. I’m adding more implementations: According to Joshua Bloch'and this is the best way to implement the Enum Singleton pattern public enum Singleton ( INSTANCE; ) Double Checked Locking & volatile public class Singleton ( private static volatile Singleton instance; public static Singleton getInstance () ( Singleton localInstance = instance; if (localInstance == null) ( synchronized (Singleton. class ) ( localInstance = instance; if (localInstance == null) ( instance = localInstance = new Singleton () ; ) ) return localInstance ) ) And also On Demand Holder idiom: public class Singleton ( public static class SingletonHolder ( public static final Singleton HOLDER_INSTANCE = new Singleton () ; ) public static Singleton getInstance () ( return SingletonHolder. HOLDER_INSTANCE; ) ) + Lazy initialization + High performance - Cannot be used for non-static class fields Any questions/suggestions - write to comments!