Php наследование singleton

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

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

singleton.php

singleton_sample.php

‘; > > //———————————————— // Реализация класса Your // // Этот класс просто расширяет функциональность // родителя, добавлением свойства $msg и его // инициализацией в конструкторе //———————————————— class Your extends Our < use Trait_Singleton; public $class_name = 'Your'; public $mgs = ''; // Реализация конструктора для класса Your protected function __construct() < parent::__construct(); $this->mgs = ‘Your random id is ‘.$this->instance_id; > > //———————————————— // Реализация класса My // // Этот класс расширяет функциональность родителя, // добавлением свойств $msg и $my_val. // При этом $my_val должен инициализироваться из // параметра конструктора. В связи с этим // необходимо переопределить фабричный метод // непосредственно в данном классе. //———————————————— class My extends Our < // use Trait_Singleton; // Не обязательно указывать, так как // единственный метод трэйта переопределен // в классе public $class_name = 'My'; public $mgs = ''; 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 и позволяют нам получить лишь по одному экземпляру каждого класса иерархии.

Навигация по записям

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

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

PHP Singleton (Синглтон)

Здравствуйте, уважаемые читатели блога LifeExample, сегодня мы будем разбираться с очередным шаблоном программирования в PHP — Синглтоном (Singleton).

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

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

Концепция шаблона Singleton

Страшное слово синглтон ассоциируемое у меня, по названию, c мелафоном из сериала «Гостья из будущего» (1984 г.), совершенно не имеет никакого сходства с машиной времени.

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

Читайте так же:  Можно ли продать долю квартиру купленную на материнский капитал

Таким образом, класс, построенный по принципу синглтона, будет защищен от многочисленного создания и дублирования действий при интерпретации кода.

Представим, что у нас есть класс, инициализирующий какие либо настройки. Для инициализации он может считывать информацию из текстовых файлов и/или таблиц БД.

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

В ходе работы системы, проведение таких операций может потребоваться очень часто, и каждый раз будет создаваться новый экземпляр класса, а соответственно будет дублироваться работа по сбору настроек из БД и файлов, что не очень лестно скажется на работе всей системы.

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

Решением этой проблемы как раз и занимается шаблон Singleton.

Обычный пример PHP Singleton

Давайте ознакомимся с концепцией и классическим примером реализации php синглтона. Взгляните на этот код:

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

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

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

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

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

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

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

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

Читайте так же:  Ук рф 130 статья

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

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

Php наследование singleton

Есть singleton и созданы два класса A и B наследующие от класса core .

Вопрос в следующем:

  1. Класса А дочерний от родительского класса core ,
  2. Класс B дочерний от родительского класса A ,

Почему же getInstance() для дочернего класса B не получает значение переменной a ?

Ошибка наследования шаблона шаблона PHP Singleton

Из класса php singleton ниже

Я пытаюсь наследовать новый дочерний класс

но когда я тестирую

Я получаю фатальную ошибку php.

PHP Неустранимая ошибка: Недоступная ошибка: не удается получить доступ к свойству SingletonChild:: $Экземпляр

Наследование Singleton class в PHP сложно, событие в PHP 7.0, но вы можете сделать это с некоторыми изменениями в вашем классе для работы.

сначала сделайте свой Singleton class до abstract

измените переменную $instance на массив $instance(s)

Теперь измените метод getInstance() , как показано ниже

И измените свой тест

помните, теперь вы не можете вызвать Singleton:: getInstance() из-за abstract

Вы сделали $instance private, что означает, что он не может быть унаследован. Измените его на protected

В руководстве обсуждается индивидуальное использование видимости

Итак, похоже, что в вашем редактировании есть зависание

Это никогда не будет правдой. getInstance получает экземпляр текущего класса. Поскольку они разные классы, они не совпадают. Однако делать такой тест неаккуратно. Я бы никогда не сделал тест на таком объекте. Что будет больше смысла, так это убедиться, что вы получаете экземпляр Singleton , который можно сделать очень легко, так

Поскольку ребенок наследует родителя, это экземпляр родительского

Правильно ли наследовать класс от синглтона?

Если нет, то почему?
Потому что в подавляющем большинстве случаев сингелтон не нужен в принципе. Избегайте использования данного шаблона проектирования по возможности.

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

А наследоваться от класса singleton не правильно как минимум с точки зрения LSP (Liskov Substitution Principle)

blnk: декорация, фасады. Что вы там расширять то собрались?

p.s. надеюсь что вы свою поделку не будете использовать в проектах-за-деньги.

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

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

Пример класса работы с бд с синглтоном и «редких» запросов есть в другом моём вопросе: PHP. Как грамотно создать дополнительный класс (ООП) для «конкретных» select’ов для работы с БД?

Читайте так же:  Документы на детское пособие повторно

blnk: поймите, вот этот вот пример с сингелтоном это по сути старое доброе процедурное программирование и работа с глобальными объектами.

Чисто ООП-way это репозитори и data mapper, полная абстракция приложения от логики хранения данных.

Основная мысль — код вашего приложения ничего не должен знать о базе данных. В частости о SQL. У вас должен быть интерфейс какого-то компонента который умеет сохранять или загружать данные, и реализация в которой вы можете уже творить все что душе угодно.

В частности вам рекомендую почитать про DAO (Data Access Object).

PHP. Singletone для pdo. Как реализовать?

Добрый день! только начинаю изучать php и ещё слаб в шаблонах проектирования, в сети наткнулся на кучу разных вариантов, но они какие-то все странные.
И встают вопросы:
1) Нужно ли вообще использовать этот шаблон для БД? И чем страшно создание множества объектов PDO?
2) Как я понял при наследовании дочерним классом класса PDO, нельзя переопределить идентификатор доступа на protected для __construct?

Написал вот такой класс для реализации singletone:

Вроде отрабатывает корректно, но был бы рад конструктивной критики в его адрес с пояснениями!)))

  • Вопрос задан более года назад
  • 1350 просмотров

Ответ на этот вопрос очень простой.

— Если ты пишешь процедурный код, то в синглтоне нет никакого вреда, а только одна польза.
— Если же ты пишешь объектный код, то синглтон тебе просто не нужен, поскольку в объект при создании всегда можно передать инстанс класса для работы с БД и присвоить переменной класса.

по поводу реализации

1. Как уже сказали выше, какой-то странный метод getInstance(). Если каждый раз вызывать с парасетрами, то какой вообще смысл в синглтоне? Сделай хотя бы два метода, один коннект, а второй гетинстанс.
2. Не очень понятно почему две статические переменные, и какая за что отвечает. почему бы не оставить одну?
3. Если уж делать синглтон, то лучше избавляться от лишней писанины, и обращаться напрямую к методам для работы с БД: `DB::insertId()` будет поудобнее, чем `DB::getInstance()->insertId()`
4. Учитывая неудобство метода PDO::execute(), будет полезным подправить классиков и добавить метод, который будет выполнять запрос с параметрами и вернет стейтмент. Пример можно посмотреть здесь: https://phpdelusions.net/pdo/pdo_wrapper

1) Нужно ли вообще использовать этот шаблон для БД? Нет. Очень часто нужно несколько соединений с СУБД.
К тому же синглтон — это антипаттерн, который маскирует зависимости.

И чем страшно создание множества объектов PDO? Несколько одинаковых не нужно. Создавайте соединение единожды, и потом просто его передавайте в другие классы. Например, через конструктор.

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

> Разве речь не про синглтон?
Я просто подсказал более удобный способ для решения проблемы автора вопроса.

> Изменится класс подключения к БД — будете по всему проекту код менять? Может лучше человеку DI посоветовать?
Ваши слова не противоречат моим. Для принимающего класса нет разницы, кто передаёт ему объект.
И если тип (не класс, т.к. тип может быть и интерфейсом) изменится, то естественно придётся всё зависимое тоже исправлять.

Php наследование singleton