Паттерн синглтон в PHP


Шаблоны проектирования в PHP: Singleton

Singleton (Синглтон, одиночка) — порождающий шаблон проектирования, гарантирует, что в приложении(однопоточном) будет использоваться только один(единственный) экземпляр класса. Объекты класса Singleton будут созданы только один раз и при последующих обращениях будет использоваться уже созданный объект, а не будут создаваться новые экземпляры. Это очень удобно и экономно. Например: соединение к БД — нам не нужно каждый раз создавать новое соединение; доступ к объекту конфигурации; в MVC — порождение главного контроллера; объект логирования.

Пример Singletone на PHP

Код выше реализует паттерн проектирования Singleton с использованием статической переменной, в которой храниться объект и метода getInstance для его создания. Обратите внимание:

1. конструктор __construct объявлен как protected, чтобы предотвратить создание нового объекта вне класса с помощью оператора new.

2. магический метод __clone объявлен как private, чтобы предотвратить клонирование объекта с помощью оператора clone.

3. магический метод __wakeup объявлен как private, чтобы предотвратить десериализацию объекта через глобальную функции unserialize().

Singleton Pattern в PHP

Дата поста: 24-05-2013

Singleton Pattern — один из наиболее известных шаблонов проектирования. Почти в любой объектно-ориентированной программе обычно существует один-два объекта, которые инициализируются в начале, и используются на всем протяжении работы приложения. Таким объектом может быть, logger — объект для ведения log-ов (log в переводе с англ. — журнал). Так в случае с log-ами, нам нет нужды каждый раз создавать объект класса logger, лишь для того, чтобы произвести запись в журнал. Достаточно создать один экземпляр класса, в начале работы программы, и пользоваться им. Такие классы (как например logger) будем называть Singleton классами.

Важно отметить, что Singleton Pattern также решает еще одну наболевшую задачу. Часто бывает так, что мы передаем в функцию (метод) параметр лишь для того, чтоб эта функция передала этот параметр еще дальше. Или же несколько частей программы постоянно нуждаются в «свежей» информации о состоянии объекта, который меняется по ходу работы; тогда снова и снова приходиться передавать объект как параметр.

Конечно, если такая ситуация возникает пару раз за всю работу приложения, можно не обращать на это внимания. Но, если один и тот же объект бестолково «футболяется» между всеми модулями и функциями программы, может возникнуть страшная путаница и, как следствие, ошибки. В таких ситуациях следует использовать Singleton класс. Вместо того, чтоб передавать по цепочке объект из функции в функцию, Singleton Pattern обеспечивает возможность, каждой части программы, получить по ссылке единственный для всей программы объект.

Вот какие преимущества дает Singleton Pattern:

  1. Мы используем ссылки на один и тот же экземпляр класса в разных частях проекта.
  2. Таким образом не нужно создавать новый объект каждый раз когда мы хотим воспользоваться каким-то методом — просто пользуемся ссылкой.
  3. Теперь не нужно передавать объект как аргумент, чтоб все части программы были «в курсе» о текущем состоянии объекта. Все ссылки указывают на один объект.

Еще раз сформулируем суть Singleton Pattern: Убедиться, что существует только один экземпляр класса и обеспечить доступ к нему из любой части программы.

Недостаток «глобального» похода

Итак, мы хотим получить только одного представителя класса и использовать его везде, где нам заблагорассудится. Казалось бы, логично ввести глобальную переменную и не загружать себе голову всякими pattern-ами. Но тут есть подвох.
Представим, что мы решили использовать глобальную переменную, содержащую singleton объект. Все нужные нам свойства есть — переменная одна и доступна отовсюду. В чем же тогда проблема? Проблема в том, что глобальная переменная непредсказуемая: у нас нет гарантии, что, на протяжении работы приложения, в ней содержится тот же объект, который мы инициализировали в начале.

У этой проблемы есть решение, но оно кривое и страшненькое. На мой взгляд классический подход лучше (на то он и классический).

Как создать singleton класс

Очень просто. В классе необходимо создать статический метод getInstance(), который возвращает единственный экземпляр класса. Если этот метод вызывается первый раз, то экземпляр класса создается, сохраняется в приватном (private), статическом (static) поле, и возвращает свеже-созданный объект. При повторном использовании метода, возвращается содержимое поля (т.е. экземпляр класса).
В следующем примере реализовано все вышесказанное.

Метод getInstance() — суть Singleton pattern. С помощью getInstance() мы можем получить доступ к объекту класса logger откуда угодно. В тоже время, методы construct() и clone(), объявленные как приватные (private), обеспечивают единственность экземпляра класса logger. Удален источник возможных ошибок — разработчик не может случайно создать еще один объект такого же типа (Такой же принцип действует и при построении value object — убрать, спрятать все методы, с помощью которых, объекты смогут ). Следовательно, getInstance()— единственный способ к представителю класса.

Что же вышло в итоге

Итак, нам удалось создать singleton класс. Мы обеспечили единственность экземпляра класса и организовали удобный доступ к нему. Что же мы выиграли, используя singleton pattern?

  • Не нужно опасаться, что наш единственный объект «подменится» по ходу работы приложения. Он надежно защищен от случайностей.
  • Из любой части программы можно легко получить объект и пользоваться им. (и вовсе не нужно рассылать его, как параметр, всем функциям или создавать каждый раз заново, чтоб использовать какой-то метод).

Паттерн Singleton следует применять очень хорошо подумав, т.к. в некоторых случаях его можно рассматривать как Антипаттерн. Речь идет о том, что Singleton часто используют просто как глобальную переменную, и в этом случае к недостаткам глобальной переменной добавляется еще и проблема существования только одного экземпляра класса.

Поэтому следует четко понимать для чего вы создаете Singleton — для глобального доступа (для чего, вообще говоря, он не предназначался), для реализации единственного экземпляра класса, либо для того и другого вместе. Если у вас слишком много Singleton‘ов в приложении, возможно, есть смысл пересмотреть его дизайн.

Вероятно также, что в случае с PHP данная проблема вообще не актуальна, т.к. задачи типа создания многопотоковых приложений, или сетевых (когда один экземпляр класса используется несколькими приложениями одновременно) перед PHP изначально не ставились.

PHP singleton

Singleton Pattern (single — единственный [англ.] ton — мода, стиль [англ.]) — один из наиболее известных шаблонов проектирования. Почти в любой объктно-ориентированной программе обычно существует один-два объекта, которые инициализируются в начале, и используются на всем протяжении работы приложения. Нет нужды каждый раз создавать объект класса, достаточно создать один экземпляр класса, в начале работы программы, и пользоваться им.


В РНР5 singleton определяется так

Пример использования

Преимущества данного метода очевидны:

  1. Мы используем ссылки на один и тот же экземпляр класса в разных частях проекта. Таким образом не нужно создавать новый объект каждый раз когда мы хотим воспользоваться каким-то методом — просто пользуемся ссылкой.
  2. Теперь не нужно передавать объект как аргумент, чтоб все части программы были «в курсе» о текущем состоянии объекта. Все ссылки указывают на один объект.

PHP 5.3

Начиная с PHP 5.3.0 была добавлена возможность Late Static Bindings, благодаря которой этот паттерн можно реализовать в виде абстрактного класса:

The singleton pattern::the good, the bad, and the ugly

Published July 05, 2015

We use the singleton pattern in order to restrict the number of instances that can be created from a resource consuming class to only one.

Resource consuming classes are classes that might slow down our website or cost money. For example:

  • Some external service providers (APIs) charge money per each use.
  • Some classes that detect mobile devices might slow down our website.
  • Establishing a connection with a database is time consuming and slows down our app.
Мастер Йода рекомендует:  Пора понять замыкания в JavaScript! Часть 1. Готовим фундамент

So, in all of these cases, it is a good idea to restrict the number of objects that we create from the expensive class to only one.

Use a singleton pattern to restrict the number of objects to only one!

The anatomy of a singleton pattern

Let’s start by understanding the structural characteristics of a class that obeys the singleton pattern:

  1. A private constructor is used to prevent the direct creation of objects from the class.
  2. The expensive process is performed within the private constructor.
  3. The only way to create an instance from the class is by using a static method that creates the object only if it wasn’t already created.

Why is it a singleton?

Since we restrict the number of objects that can be created from a class to only one, we end up with all the variables pointing to the same, single object.

Practical example::database class

Let’s demonstrate the singleton pattern with a class that establishes a database connection, and restricts the number of instances to only one.

Since we use a class that checks if a connection already exists before it establishes a new one, it really doesn’t matter how many times we create a new object out of the class, we still get the same connection. To prove the point, let’s create three instances out of the class and var dump them.

The result is the same connection for the three instances.

Class that doesn’t use a singleton to contact the database

To understand the problem that the singleton pattern solves, let’s consider the following class that has no mechanism to check if a connection already exists before it establishes a new connection.

Now, each time we create a new object, we also establish a new database connection.


This has implications for slowing down the system because each new connection with the database costs time.

I encourage you to run the code to see the result for yourself.

The singleton pattern::the good, the bad, and the ugly

The singleton pattern is probably the most infamous pattern to exist, and is considered an anti-pattern because it creates global variables that can be accessed and changed from anywhere in the code.

Yet, The use of the singleton pattern is justified in those cases where we want to restrict the number of instances that we create from a class in order to save the system resources. Such cases include data base connections as well as external APIs that devour our system resources.

Joseph Benharosh is a full stack web developer and the author of the eBook The essentials of object oriented PHP.

Creating the Singleton design pattern in PHP5

How would one create a Singleton class using PHP5 classes?

20 Answers 20

Throws an error.

PHP 5.3 allows the creation of an inheritable Singleton class via late static binding:

This solves the problem, that prior to PHP 5.3 any class that extended a Singleton would produce an instance of its parent class instead of its own.

And $foo will be an instance of Foobar instead of an instance of Singleton.

Unfortunately Inwdr’s answer breaks when there are multiple subclasses.

Here is a correct inheritable Singleton base class.

The Real One and Modern way to make Singleton Pattern is:

So now you can use it like.

As you see this realization is lot more flexible.

You probably should add a private __clone() method to disallow cloning of an instance.

If you don’t include this method the following gets possible

now $inst1 !== $inst2 — they are not the same instance any more.

If you are using PHP 5.4: trait its an option, so you don’t have to waste the inheritance hierarchy in order to have the Singleton pattern

and also notice that whether you use traits or extends Singleton class one loose end was to create singleton of child classes if you dont add the following line of code:

in the child class

the unexpected result will be:

This code can apply for any class without caring about its class name.

Supports Multiple Objects with 1 line per class:

This method will enforce singletons on any class you wish, al you have to do is add 1 method to the class you wish to make a singleton and this will do it for you.

This also stores objects in a «SingleTonBase» class so you can debug all your objects that you have used in your system by recursing the SingleTonBase objects.

Create a file called SingletonBase.php and include it in root of your script!


Then for any class you want to make a singleton just add this small single method.

Here is a small example:

And you can just add this singleton function in any class you have and it will only create 1 instance per class.

NOTE: You should always make the __construct private to eliminate the use of new Class(); instantiations.

You don’t really need to use Singleton pattern because it’s considered to be an antipattern. Basically there is a lot of reasons to not to implement this pattern at all. Read this to start with: Best practice on PHP singleton classes.

If after all you still think you need to use Singleton pattern then we could write a class that will allow us to get Singleton functionality by extending our SingletonClassVendor abstract class.

This is what I came with to solve this problem.

Just to prove that it works as expected:

All this complexity («late static binding» . harumph) is, to me, simply a sign of PHP’s broken object/class model. If class objects were first-class objects (see Python), then «$_instance» would be a class instance variable — a member of the class object, as opposed to a member/property of its instances, and also as opposed to shared by its descendants. In the Smalltalk world, this is the difference between a «class variable» and a «class instance variable».

In PHP, it looks to me as though we need to take to heart the guidance that patterns are a guide towards writing code — we might perhaps think about a Singleton template, but trying to write code that inherits from an actual «Singleton» class looks misguided for PHP (though I supposed some enterprising soul could create a suitable SVN keyword).

I will continue to just code each singleton separately, using a shared template.

Notice that I’m absolutely staying OUT of the singletons-are-evil discussion, life is too short.

I know this is probably going to cause an unnecessary flame war, but I can see how you might want more than one database connection, so I would concede the point that singleton might not be the best solution for that. however, there are other uses of the singleton pattern that I find extremely useful.

Here’s an example: I decided to roll my own MVC and templating engine because I wanted something really lightweight. However, the data that I want to display contains a lot of special math characters such as ≥ and μ and what have you. The data is stored as the actual UTF-8 character in my database rather than pre-HTML-encoded because my app can deliver other formats such as PDF and CSV in addition to HTML. The appropriate place to format for HTML is inside the template («view» if you will) that is responsible for rendering that page section (snippet). I want to convert them to their appropriate HTML entities, but PHPs get_html_translation_table() function is not super fast. It makes better sense to retrieve the data one time and store as an array, making it available for all to use. Here’s a sample I knocked together to test the speed. Presumably, this would work regardless of whether the other methods you use (after getting the instance) were static or not.

Мастер Йода рекомендует:  Спасите сайт! 10 советов по безопасности веб-приложений

Basically, I saw typical results like this:

So while I’m certainly no expert, I don’t see a more convenient and reliable way to reduce the overhead of slow calls for some kind of data, while making it super simple (single line of code to do what you need). Granted my example only has one useful method, and therefore is no better than a globally defined function, but as soon as you have two methods, you’re going to want to group them together, right? Am I way off base?

Also, I prefer examples that actually DO something, since sometimes it’s hard to visualise when an example includes statements like «//do something useful here» which I see all the time when searching for tutorials.

Anyway, I’d love any feedback or comments on why using a singleton for this type of thing is detrimental (or overly complicated).

Шаблоны проектирования: Singleton, Factory

Дата публикации: 2014-02-24

От автора: при разработке веб-приложений разработчикам очень часто приходится решать одни и те же задачи, которые с течением времени стали типовыми. Поэтому для их решения были придуманы так называемые шаблоны проектирования. В данном уроке я хотел бы рассмотреть два наиболее полезных и часто применяемых шаблона проектирования.

Введение

Как я и говорил выше, шаблоны проектирования решают типовые задачи в веб-программировании. Но это не готовое решение одной из задач, которое можно скачать и применить у себя на практике. Это — скорее всего метод, или идея того, как можно решить ту или иную задачу. Использование данных шаблонов помогает значительно ускорить процесс разработки, так как Вы не тратите время на изобретение велосипеда, помогает выработать общую стратегию в построении иерархии в создаваемом скрипте. Так же использование шаблонов проектирования помогает в документировании работы отдельных узлов Вашего веб-приложения. Так как, поясняя работу участка кода, Вы можете сказать, что он построен на базе шаблона Singtone, и знающий человек сразу поймет, в чем дело. Поэтому, знать, что такое шаблоны проектирования должен каждый хороший разработчик.

Конечно, шаблонов придумано большое количество и все их в данном уроке мы рассмотреть не сможем. Но мы рассмотрим два наиболее часто используемых, которые могут пригодиться в Вашей практике.

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

Singleton

Давайте рассмотрим код следующего файла:

Соединение с базой данных

Как Вы видите, в нем описан несложный класс, предназначенный для работы с базой данных. Который, в конструкторе выполняет соединение с базой данных. То есть при создании объекта выполняется соединение с базой данных. Теперь, логично бы было, если один раз в скрипте будет создан объект данного класса. И вся последующая работа сводилась к обычному обращению к этому объекту.


Но что будет, если создать несколько объектов данного класса? Как в нашем примере. В этом случае будет три раза вызван метод конструктора, а вместе с ним будет выполнено три подключения к базе данных. Что не очень хорошо в плане быстродействия и затраченных ресурсов. Это легко проверить, если выполнить данный скрипт в браузере:

Поэтому для подобных классов, необходимо обеспечить возможность создания только одного объекта и не больше.
Для решения данной задачи применяется шаблон проектирования Singleton. Данный шаблон гарантирует, что у определенного класса можно будет создать только один объект.

Важное условие работы Singlton: необходимо закрыть публичный доступ для конструктора класса, а также запретить публичное клонирование объекта. Для этого достаточно добавить спецификатор доступа private для соответствующих методов класса:

Pattern Singleton – «Одиночка»

Паттерн Singleton (одиночка) многие ругают, зачастую, называя его анти паттерном. Тем не менее, он достаточно популярен и я пока не встречал крупных программных систем, где он не был бы реализован. Прежде всего, можно отметить фреймворки, где Singleton нередко выступает основой приложения. Также его часто наследуют компоненты, реализующие взаимодействие с конфигурационными данными или механизмом событий, например.

Основной проблемой данного паттерна является подкупающая простота его реализации и использования. Разработчики, не имеющие достаточного количества опыта, применяют Singleton там, где он совершенно не нужен, тем самым лишая программную систему гибкости и пригодности к адекватному тестированию.

Для того чтобы описать шаблон проектирования, сначала необходимо описать задачу, которую он будет решать.

Предположим, что в вашем приложении есть объект, в котором хранятся данные конфигурации приложения. Разумеется, данные конфигурации должны быть доступны разным частям приложения на всех уровнях.

Согласно идеологии ООП, для получения доступа к переменной, например, внутри метода объекта, ее необходимо передать в качестве параметра этого метода или конструктора. Необходимо стараться следовать этому принципу всегда, когда это возможно. Но, в описанной ситуации, трудно представить, через какое количество объектов придется протащить экземпляр класса работы с конфигом.
В PHP есть два способа поместить данные в глобальную область видимости, тем самым, сделать их доступными из любого места программы. Первый – использование суперглобального ассоциативного массива $GLOBALS , содержащего все переменные, объявленные в глобальной области видимости. Второй – использование ключевого слова global , вводящего переменную в текущую область видимости. Какой способ хуже, я затрудняюсь даже предположить. Как бы там ни было, в других языках программирование подобные средства отсутствуют и паттерн Singleton становится единственным способом введения объекта в глобальное пространство.

Класс, реализующий паттерн Singleton становится доступным глобально за счет статического интерфейса. Также к числу его особенностей необходимо отнести блокирование конструктора класса и магических методов __clone() и __wakeup() , описывая их с модификатором доступа private . Это делается для того, чтобы не допустить создание более одного объекта от класса.

Единственное свойство класса Singleton::$_instance хранит ссылку на экземпляр, который создается только при первом вызове статического метода Singleton::getInstance() . От повторного создания объекта уберегает условный оператор, с проверкой значения свойства и если ссылка на экземпляр уже существует, она будет возвращена.

Свойство Singleton::$_instance объявлено с модификатором protected , дабы класс можно было наследовать. Нередко паттерн реализуют с сокрытием этого свойства за модификатором private.

Реализацию шаблона Одиночка можно посмотреть, например, в классе CI_Controller из фреймворка CodeIgniter или Zend_Controller_Front из ZendFramework.

Создание шаблона проектирования Singleton в PHP5

Как создать класс Singleton с использованием классов PHP5?

См. Http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static, чтобы понять области статических переменных и зачем устанавливать static $inst = null; работает.

PHP 5.3 позволяет создать наследуемый класс Singleton через позднюю статическую привязку:

Это решает проблему, что до PHP 5.3 любой класс, который расширил Singleton, создавал бы экземпляр своего родительского класса вместо его собственного.

Теперь вы можете сделать:

И $foo будет экземпляром Foobar вместо экземпляра Singleton.

К сожалению ответ Inwdr ломается, когда есть несколько подклассов.

Вот правильный наследуемый базовый класс Singleton.

Реальный и современный способ создания Singleton Pattern:

Итак, теперь вы можете использовать его как.

Как вы видите, эта реализация намного более гибкая.

Вероятно, вы должны добавить частный метод __clone(), чтобы запретить клонирование экземпляра.

Если вы не включили этот метод, возможно следующее:

now $inst1 ! == $inst2 — они уже не те же самые экземпляры.

Этот код может применяться для любого класса, не заботясь о его имени класса.

Если вы используете PHP 5.4: trait свой вариант, вам не нужно тратить иерархию наследования, чтобы иметь шаблон Singleton


а также обратите внимание, что если вы используете черты или , расширяете Singleton класс одним свободным концом было создание singleton дочерних классов, если вы не добавляете следующую строку кода:

в дочернем классе

неожиданным результатом будет:

Поддержка нескольких объектов с 1 строкой для каждого класса:

Этот метод обеспечит соблюдение синглетонов в любом классе, который вам нужен, но вам нужно добавить один метод в класс, который вы хотите создать синглтон, и это сделает это за вас.

Это также сохраняет объекты в классе «SingleTonBase», поэтому вы можете отлаживать все свои объекты, которые вы использовали в вашей системе, путем рекурсии объектов SingleTonBase .

Создайте файл с именем SingletonBase.php и включите его в корень из script!

Затем для любого класса, который вы хотите сделать singleton, просто добавьте этот небольшой единственный метод.

Мастер Йода рекомендует:  Принципы функционального программирования почему это важно

Вот небольшой пример:

И вы можете просто добавить эту одноэлементную функцию в любой класс, который у вас есть, и он будет создавать только один экземпляр для каждого класса.

ПРИМЕЧАНИЕ. Вы всегда должны сделать __construct частным, чтобы исключить использование нового класса(); конкретизации.

Вся эта сложность ( «поздняя статическая привязка». харумф) для меня — это просто признак PHP сломанной модели объекта/класса. Если объекты класса были первоклассными объектами (см. Python), то «$ _instance» будет переменной экземпляра класса — членом объекта класса, в отличие от элемента/свойства его экземпляров, а также в отличие от общих его потомками. В мире Smalltalk это различие между «переменной класса» и «переменной экземпляра класса».

В PHP мне кажется, что нам нужно принять близко к сердцу руководство, что шаблоны являются руководством к написанию кода — возможно, мы подумаем о шаблоне Singleton, но пытаемся написать код, который наследуется от фактического «Singleton» выглядит ошибочно для PHP (хотя я предположил, что какая-то предприимчивая душа может создать подходящее ключевое слово SVN).

Я буду продолжать просто кодировать каждый синглтон отдельно, используя общий шаблон.

Обратите внимание на то, что я полностью остаюсь вне обсуждения в одиночном одиночестве, жизнь слишком коротка.

Я знаю, что это, вероятно, вызовет ненужную пламенную войну, но я вижу, как вам может понадобиться более одного соединения с базой данных, поэтому я бы уступил точке, что синглтон может не быть лучшим решением для этого. однако, существуют другие применения одноэлементного шаблона, которые я считаю чрезвычайно полезными.

Вот пример: я решил свернуть свой MVC и шаблонный движок, потому что мне хотелось что-то очень легкое. Однако данные, которые я хочу отображать, содержат множество специальных математических символов, таких как & ge; и & mu; и что у вас есть. Данные хранятся как фактический символ UTF-8 в моей базе данных, а не pre-HTML-кодирование, потому что мое приложение может поставлять другие форматы, такие как PDF и CSV, в дополнение к HTML. Соответствующее место для форматирования HTML находится внутри шаблона ( «вид», если вы это сделаете), который отвечает за рендеринг этого раздела (фрагмента). Я хочу преобразовать их в соответствующие HTML-объекты, но функция get_html_translation_table() PHP не является очень быстрой. Имеет смысл извлекать данные один раз и хранить в виде массива, что делает его доступным для всех. Здесь образец, который я опрокинул, чтобы проверить скорость. Предположительно, это будет работать независимо от того, были ли другие методы, которые вы используете (после получения экземпляра), были статическими или нет.

В основном, я видел типичные результаты следующим образом:

Поэтому, хотя я, конечно, не эксперт, я не вижу более удобного и надежного способа уменьшить накладные расходы медленных вызовов для каких-то данных, делая его очень простым (одна строка кода, чтобы делать то, что вы необходимость). Предоставленный мой пример имеет только один полезный метод и, следовательно, не лучше, чем глобально определенная функция, но как только у вас есть два метода, вы захотите объединить их вместе, не так ли? Я в стороне от базы?

Кроме того, я предпочитаю примеры, которые на самом деле что-то делают, поскольку иногда трудно представить, когда пример включает в себя такие выражения, как «//делаем что-то полезное здесь», которое я все время вижу при поиске учебников.

В любом случае, мне бы хотелось, чтобы любые отзывы или комментарии о том, почему использование одноэлементного для этого типа вещей являются вредными (или чрезмерно сложными).

Шаблон проектирования «Одиночка»(Pattern Singleton).

Сегодня я хочу разобрать шаблон проектирования «одиночка», который очень часто используется в объектно-ориентированном программировании.

Шаблон проектирования «Одиночка» или Pattern Singleton нужен для того, чтобы у нас не было много однотипных объектов, а всегда использовался только один. В качестве примера можно привести класс для работы с базой данных.

class DB <
protected $db;

public function __construct() <
$this->db = new Mysqli($host, $user, $pass, $database);
>

public function get() <>
public function set() <>
public function del() <>
>

$db1 = new DB();
$db2 = new DB();

У нас уже 2 объекта $db1 и $db2, а потом кто-нибудь, не зная, что уже есть такой объект, создаст третий и т.д. Это очень плохо сказывается на производительности и читаемости кода, а в нашем случае может произойти сбой, т.к. на хостинге ограниченное количество подключений к базе данных.

Чтобы решить эту проблему, и был придуман паттерн singleton.


class DB <
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(); // ошибка

$db = DB::getInstance();
$db2 = DB::getInstance();
$db3 = DB::getInstance();

Чтобы создать объект обычным способом было нельзя, мы делаем наш конструктор приватным, но также не забываем и про то, что объекты могут клонироваться и закрываем также метод __clone. Дальше мы создаём статическое свойство $instance, которое по умолчанию равно null. Теперь создаём статический метод getInstance(), который проверяет, равно ли наше статическое свойство null? Если да, то мы создаём экземпляр нашего объекта и возвращаем его, а если же нет, то просто возвращаем его. Таким образом, у нас всегда будет один и тот же экземпляр, сколько бы мы их не создавали. Использовать его очень просто: присваиваем переменной значение, которое возвращает статический метод getInstance(), класса DB, а дальше работаем, как и с обычным объектом.

Итак, сегодня вы узнали, что такое паттерн singleton, а, главное, зачем он нужен и где его применять.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (https://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: https://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: https://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Она выглядит вот так:

  • BB-код ссылки для форумов (например, можете поставить её в подписи):
  • Комментарии ( 3 ):

    Спасибо, очень полезная статья! Продолжайте пожалуйста писать о шаблонах проектирования.

    Спасибо за отзыв. Будем)

    Здравствуйте! Подскажите пожалуйста каким образом созданный экземпляр объекта подключения к БД, который в конструкторе сохраняется в $this-db попадает в свойство $instance? Я не вижу смысла создавать свойство db если в конструкторе нужно всего лишь вернуть соединение, которое в методе getInstance() присвоится в свойство $instance.

    Для добавления комментариев надо войти в систему.
    Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

    Copyright © 2010-2020 Русаков Михаил Юрьевич. Все права защищены.

    LimanWorld

    Паттерн Singleton (Одиночка) уже многократно обсуждался, тем не менее я не нашел решения позволяющего реализовать наследование от Singleton-а не нарушающего основной идеи Singleton-а — скрытие конструктора класса.

    Ниже приведен пример моей реализации такого механизма не нарушающего сущность паттерна с использованием трэйта.

    singleton.php

    singleton_sample.php

    ‘; > > //———————————————— // Реализация класса Your // // Этот класс просто расширяет функциональность // родителя, добавлением свойства $msg и его // инициализацией в конструкторе //———————————————— ; // Реализация конструктора для класса Your protected function __construct() < parent::__construct(); $this->mgs = ‘Your random id is ‘.$this->instance_ ; public $my_val; // Перекрываем фабричный метод трэйта, так как // надо передать параметр public static function getInstance($val=null) < static $_instance; if ($_instance === null) < $_instance = new self($val); >return $_instance; > // Реализация конструктора для класса My protected function __construct($val=null) < parent::__construct(); $this->mgs = ‘My random id is ‘.$this->instance_id; $this->my_val = $val; > > //=============================================== // Пример использования //=============================================== // Создаем экземпляр Your $O1 = Your::getInstance(‘1st Your’); $O1->showMe(); $O2 = Your::getInstance(‘2nd Your’); $O2->showMe(); // Создаем экземпляр My $O3 = My::getInstance(‘My Value . ‘); $O3->showMe(); $O4 = My::getInstance(); $O4->showMe(); // Создаем экземпляр Our $O5 = Our::getInstance(); $O5->showMe(); $O6 = Our::getInstance(); $O6->showMe(); ?>

    Таким образом, мы получаем некоторую иерархию классов, которые наследуются от Singleton и позволяют нам получить лишь по одному экземпляру каждого класса иерархии.

    Добавить комментарий Отменить ответ

    Для отправки комментария вам необходимо авторизоваться.

    Добавить комментарий