Чи є регістр використання для одиночних клавіш з доступом до бази даних в PHP?


138

Я отримую доступ до своєї бази даних MySQL через PDO. Я налаштовував доступ до бази даних, і першою моєю спробою було використання наступного:

Перше, що я подумав global:

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');

function some_function() {
    global $db;
    $db->query('...');
}

Це вважається поганою практикою. Після невеликого пошуку я закінчив малюнок Singleton , який

"застосовується до ситуацій, коли потрібно мати один екземпляр класу."

Відповідно до прикладу в посібнику, ми повинні зробити це:

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }
}

function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');
}

some_function();

Навіщо мені потрібен такий відносно великий клас, коли я можу це зробити?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }
}

function some_function() {
    Database::get()->query('...');
}

some_function();

Цей останній працює чудово, і мені більше не потрібно хвилюватися $db.

Як я можу створити менший клас одиночних класів, або чи є випадки використання для одиночних клавіш, які мені відсутні в PHP?


У цьому пов'язаному питанні є багато ресурсів та дискусій: "Що так погано в одинакових?"
FruitBreak

Відповіді:


80

Гаразд, я замислювався над тим, коли я вперше розпочав свою кар’єру. Реалізовували його різними способами і придумали дві причини не використовувати статичні класи, але вони досить великі.

Одне полягає в тому, що ви дуже часто знайдете те, в чому ви абсолютно впевнені, що ніколи не будете мати більше ніж один екземпляр, у підсумку ви матимете другий. Ви можете отримати другий монітор, другу базу даних, другий сервер - що завгодно.

Коли це трапляється, якщо ви використовували статичний клас, ви знаходитесь в набагато гіршому рефакторі, ніж якщо б ви використовували синглтон. Однотонний - сам по собі шаблон, але він досить легко перетворюється на розумний заводський зразок - його можна навіть перетворити на використання ін'єкційних залежностей без зайвих проблем. Наприклад, якщо ваш синглтон отриманий через getInstance (), ви можете легко змінити це на getInstance (databaseName) і дозволити кілька баз даних - інших кодів не змінюється.

Другий випуск - тестування (І якщо чесно, це те саме, що і перший випуск). Іноді ви хочете замінити свою базу даних на макетну базу даних. По суті це другий екземпляр об’єкта бази даних. З статичними класами це зробити набагато складніше, ніж з синглтоном, потрібно лише знущатися з методу getInstance (), а не з кожного методу статичного класу (що в деяких мовах може бути дуже важким).

Це дійсно зводиться до звичок - і коли люди кажуть, що "Глобали" погані, у них є дуже вагомі причини так сказати, але це не завжди може бути очевидним, поки ти сам не вдариш про проблему.

Найкраще, що ви можете зробити, це запитати (як і ви), а потім зробити вибір і дотримуватися наслідків свого рішення. Знання для інтерпретації еволюції коду з часом набагато важливіше, ніж це робити в першу чергу правильно.


15
Ви кажете, що одиночні файли чудово деградують до DI, але чи не є вашим прикладом getInstance(databaseName)просто розсіювання посилань на глобальне сховище екземплярів у вашому коді? Код, який викликав би, getInstanceповинен містити екземпляр (и), введений в нього клієнтським кодом, і тому getInstanceв першу чергу не потрібно викликати .
Буде Вузден

1
@Will Wousden Правильно, це свого роду зупинка. Це насправді не DI, але це може бути досить близько. Наприклад, що робити, якщо це було getInstance (підтримується база даних), а повернений екземпляр розраховувався на основі того, яку базу даних передали? Сенс у тому, щоб не лякати людей із рамками DI, поки вони не будуть готові до цього.
Білл К

320

Синглтонів дуже мало - якщо не сказати ні - використання в PHP.

У мовах, де об’єкти живуть у спільній пам'яті, Singletons можна використовувати для зменшення використання пам'яті. Замість створення двох об'єктів ви посилаєтесь на існуючий екземпляр із загальнодоступної пам'яті додатків. У PHP немає такої пам’яті додатків. Сінглтон, створений в одному запиті, діє саме для цього запиту. Сінглтон, створений в іншому запиті, виконаному одночасно, все ще є зовсім іншим екземпляром. Таким чином, одна з двох основних цілей Сінглтона тут не застосовується.

Крім того, для багатьох об'єктів, які концептуально можуть існувати лише один раз у вашій програмі, не обов'язково потрібен мовний механізм для цього. Якщо вам потрібен лише один екземпляр, не інстанціюйте інший . Лише тоді, коли у вас може бути інший екземпляр, наприклад, коли кошенята гинуть під час створення другої інстанції, у вас може бути дійсний приклад використання для сингтона.

Іншою метою було б мати глобальну точку доступу до екземпляра в межах одного запиту. Хоча це може здатися бажаним, воно насправді не є, оскільки воно створює зв'язок із глобальною сферою (як і будь-яка глобальна та статична). Це робить Unit-Testing більш складним, а ваш додаток загалом менш реальним. Існують способи пом'якшити це, але загалом, якщо вам потрібно мати один і той же екземпляр у багатьох класах, використовуйте Dependency Injection .

Дивіться мої слайди для Singletons у PHP - Чому вони погані та як їх можна усунути зі своїх додатків для отримання додаткової інформації.

Навіть Еріх Гамма , один із винахідників схеми Сінглтона, сумнівається в цій моделі сьогодні:

"Я за те, щоб скинути Singleton. Його використання майже завжди дизайнерський запах"

Подальше читання

Якщо після вищезазначеного вам все-таки потрібна допомога у вирішенні:

Діаграма рішення одиночної форми


1
@ Гордон так. І навіть якби вдалося підтримувати об'єкти між запитами, Сінглтонт все одно порушує пару принципів SOLID та впроваджує Global State.
Гордон

4
Вибачте, що йдіть проти потоку, але DI насправді не вирішує проблему, для якої використовується Singleton, якщо ви не задоволені тим, що вам потрібні класи з 42 параметрами ctor (або 42 виклики setFoo () та setBar (), щоб зробити це робота). Так, деякі програми, на жаль, мають бути поєднані та залежать від багатьох зовнішніх речей. PHP - це клейова мова, і іноді склеювати багато речей.
StasM

14
@StasM якщо у вас 42 ctor params або вам потрібно багато сетерів, ви робите це неправильно. Дивіться будь-ласка, чисті кодові переговори. Вибачте, якщо мені не вдасться пояснити це ще раз. Не соромтеся запитати в кімнаті PHP для отримання додаткової інформації.
Гордон

@Gordon Де знаходиться кімната для чату php?
користувач658182

21

Кому потрібні сингли в PHP?

Зауважте, що майже всі заперечення проти синглів виходять з технічних позицій - але вони також ДУЖЕ обмежені у своєму обсязі. Спеціально для PHP. Спочатку я перерахую деякі причини використання синглів, а потім проаналізую заперечення проти використання синглів. По-перше, люди, які їм потрібні:

- Люди, які кодують велику рамку / кодову базу, яка буде використовуватися в багатьох різних середовищах, повинні будуть працювати з раніше існуючими, різними рамками / кодами, з необхідністю реалізації багатьох різних, мінливих, навіть примхливих запитів від клієнтів / начальників / керівництво / керівники підрозділів.

Дивіться, однотонний малюнок є самовключним. Після закінчення однокласного класу є жорстким для будь-якого коду, до якого ви його включаєте, і він діє точно так, як ви створили його методи та змінні. І це завжди той самий об’єкт у заданому запиті. Оскільки його не можна створити двічі для двох різних об'єктів, ви знаєте, що є однотонним об’єктом у будь-якій точці коду - навіть якщо синглтон вставлений у дві, три різні, старі, навіть спагеті кодові бази. Тому це полегшує з точки зору цілей розробки - навіть якщо в цьому проекті працює багато людей, коли ви бачите одиночний ініціалізацію в одній точці в будь-якій заданій кодовій базі, ви знаєте, що це, що робить, як це так, і про стан, в якому він знаходиться. Якби це був традиційний клас, вам потрібно було б відслідковувати, де вперше створений цей об’єкт, які методи викликалися в ньому до цього моменту в коді та його конкретний стан. Але киньте туди синглтон, і якщо ви скинули належні методи налагодження та інформації та відстеження в синглтон, кодуючи його, ви точно знаєте, що це таке. Таким чином, це полегшує людям, яким доводиться працювати з різними базами коду, з необхідністю інтегрувати код, який був зроблений раніше з різними філософіями, або зроблений людьми, з якими ви не маєте контакту. (тобто, постачальник-проект-компанія-що б там не було більше, немає нічого підтримки). це полегшує людям, яким доводиться працювати з різними базами коду, з необхідністю інтегрувати код, який був зроблений раніше з різними філософіями, або робиться людьми, з якими ви не маєте контакту. (тобто, постачальник-проект-компанія-що б там не було більше, немає нічого підтримки). це полегшує людям, яким доводиться працювати з різними базами коду, з необхідністю інтегрувати код, який був зроблений раніше з різними філософіями, або робиться людьми, з якими ви не маєте контакту. (тобто, постачальник-проект-компанія-що б там не було більше, немає нічого підтримки).

- Люди, яким потрібно працювати з сторонніми API , службами та веб-сайтами.

Якщо ви придивитесь ближче, це не надто відрізняється від попереднього випадку - сторонні API, сервіси та веб-сайти - це як зовнішні, ізольовані кодові бази, над якими у вас немає контролю. Все може статися. Отже, за допомогою одиночного сеансу / класу користувача ви можете керувати будь-яким видом сеансу / авторизації від сторонніх постачальників, таких як OpenID , Facebook , Twitter та багато іншого - і ви можете робити ВСІ водночас із об’єкта SAME Singleton - який є легкодоступним, у відомому стані в будь-який момент будь-якого коду, до якого ви підключите його. Ви навіть можете створити кілька сеансів для декількох сторонніх API / служб для користувача SAME на власному веб-сайті / програмі та робити все, що ви хочете зробити з ними.

Звичайно, все це також може бути в тон з традиційними методами, використовуючи звичайні класи та об'єкти - улов тут є, одинарніше акуратніше, акуратніше, а тому через це керованість / тестування легше порівняно з традиційним використанням класу / об’єкта в таких ситуаціях.

- Люди, яким потрібно робити швидкий розвиток

Глобальна поведінка одинаків полегшує побудову будь-якого коду з рамкою, на якій є колекція синглів, щоб побудувати, тому що, коли ви добре сконструюєте свої однотонні класи, легко встановити встановлені, зрілі та встановлені методи може використовуватися в будь-якому місці і в будь-який час, послідовно. Щоб дозріти ваші заняття, потрібен певний час, але після цього вони є міцними і стійкими, корисними. Ви можете мати стільки методів в одиночному виконанні всього, що ви хочете, і, хоча це може збільшити слід пам'яті об'єкта, це приносить набагато більше економії часу, необхідного для швидкої розробки - метод, який ви не використовуєте в одному заданому екземплярі додаток можна використовувати в іншому інтегрованому, і ви можете просто заштрихувати нову функцію, про яку клієнт / начальник / менеджер проекту вимагає лише декількох модифікацій.

Ви отримуєте ідею. Тепер перейдемо до заперечень одинаків та нечесного хрестового походу проти чогось корисного :

- Найперше заперечення полягає в тому, що це ускладнює тестування.

І справді, це певною мірою, навіть якщо це можна легко пом'якшити, вживши належних запобіжних заходів та кодуючи підпрограми налагодження у ваших сингтонах З усвідомленням того, що ви будете налагоджувати одиноку. Але бачте, це не надто відрізняється від будь-якої іншої філософії / методу / шаблону кодування, яка існує там - це просто те, що одинаки є відносно новими і не широко поширеними, тому сучасні методи тестування закінчуються порівняно несумісними з ними. Але це не відрізняється в будь-якому аспекті мов програмування - різні стилі вимагають різних підходів.

Один момент, який заперечує, заперечує те, що він ігнорує той факт, що розроблені додатки не для "тестування", а тестування - не єдина фаза / процес, що переходить у розробку додатків. Програми розроблені для виробничого використання. І як я пояснив у розділі "кому потрібні одиночні кнопки", одиночні кнопки можуть вирізати ВЕЛИКУ угоду від складності необхідності змусити код працювати З І ВНУТРИ багато різних баз коду / додатків / сторонніх послуг. Час, який може бути втрачено на тестування, - це час, отриманий на розробку та впровадження. Це особливо корисно в цю епоху сторонніх аутентифікацій / застосувань / інтеграцій - Facebook, Twitter, OpenID, багато інших і хто знає, що далі.

Хоча це і зрозуміло - програмісти працюють у дуже різних обставинах залежно від їх кар’єри. А людям, які працюють у порівняно великих компаніях з визначеними відділами, які комфортно і без певної приреченості скорочення / скорочення бюджету та супутньої необхідності створюють багато певного програмного забезпечення / додатків, що супроводжують необхідність робити багато речей із великою кількістю різних матеріалів дешева / швидка / надійна мода, одинаки можуть здатися не потрібними. І це може бути навіть неприємністю / перешкодою для того, що вони ВЖЕ мають.

Але для тих, кому потрібно працювати в брудних окопах "спритного" розвитку, що мають реалізувати багато різних запитів (іноді необгрунтованих) від свого клієнта / менеджера / проекту, одинаки - це заощаджувальна благодать із пояснених раніше причин.

- Ще одне заперечення полягає в тому, що слід пам'яті вище

Оскільки для кожного запиту від кожного клієнта буде новий синглтон, це може бути запереченням для PHP. При погано побудованих та використаних одиночних кнопках слід пам'яті програми може бути вищим, якщо додаток обслуговується багатьма користувачами в будь-якій точці.

Хоча це справедливо для будь-якого підходу, який ви можете використовувати під час кодування речей. Питання, які слід задати: чи не потрібні методи, дані, які зберігаються та обробляються цими однотонними? Оскільки, якщо вони потрібні для багатьох запитів, що надходять до програми, то навіть якщо ви не використовуєте одиночні кнопки, ці методи і дані будуть представлені у вашій програмі в тій чи іншій формі через код. Отже, все стає питанням, скільки пам’яті ви будете економити, коли ініціалізуєте традиційний об’єкт класу 1/3 в обробку коду та знищите його на 3/4.

Дивіться, якщо це зробити так, питання стає зовсім неактуальним - не повинно бути зайвих методів, даних, що містяться в об'єктах у вашому коді, будь-коли - незалежно від того, використовуєте ви одноразові чи ні. Таким чином, це заперечення проти одиночних класів стає насправді веселим, тому ВИМОГАЄМО, що в об’єктах, створених із класів, якими ви користуєтесь, будуть зайві методи, дані.

- Деякі недійсні заперечення на зразок "робить неможливим / важчим підтримання кількох з'єднань баз даних"

Я навіть не можу почати розуміти це заперечення, коли всім потрібно підтримувати декілька підключень до бази даних, кілька виборів баз даних, кілька запитів баз даних, безліч наборів результатів у заданому синглетоні, просто зберігаючи їх у змінних / масивах у синглтоні, поки вони потрібні. Це може бути так само просто, як зберігати їх у масивах, хоча ви можете придумати будь-який метод, який ви хочете використовувати для цього. Але давайте розглянемо найпростіший випадок, використання змінних та масивів у заданому синглетоні:

Уявіть, що нижче знаходиться всередині даної бази даних одиночне:

$ this -> connection = array (); (неправильний синтаксис, я просто набрав це так, щоб дати вам зображення - правильне оголошення змінної є загальнодоступним $ connections = array (); його використання - це $ this-> connection ['connectionkey'] природно)

Ви можете налаштувати та зберігати декілька з'єднань у будь-який момент у масиві таким чином. І те саме стосується запитів, наборів результатів тощо.

$ this -> query (QUERYSTRING, 'queryname', $ this-> connection ['particulrconnection']);

Який може просто зробити запит до вибраної бази даних із вибраним з'єднанням і просто зберігати у вашому

$ this -> результати

масив з ключем 'ім'я запиту'. Звичайно, для цього вам потрібно буде закодувати метод запиту - що тривіально.

Це дозволяє підтримувати практично нескінченну кількість (стільки, скільки дозволяють обмеження ресурсів,) різних підключень до бази даних та наборів результатів стільки, скільки вам потрібно. І вони доступні для будь-якого фрагмента коду в будь-якій точці будь-якої заданої кодової бази, до якої цей однотонний клас був інстанційований.

КУРСУ, природно, вам потрібно буде звільнити набори результатів і з'єднання, коли вони не потрібні, але це само собою зрозуміло, і це не характерно для одиночних клавіш або будь-якого іншого методу / стилю / концепції кодування.

На цьому етапі ви можете побачити, як ви можете підтримувати декілька з'єднань / станів із сторонніми додатками чи послугами в одному синглонті. Не так інакше.

Коротше кажучи, зрештою, однотонні візерунки - це лише ще один метод / стиль / філософія, з яким можна запрограмувати, і вони такі ж корисні, як і будь-які інші, коли їх використовують у правильному місці, у правильному порядку. Що нічим не відрізняється.

Ви помітите, що в більшості статей, в яких сингли забиті, ви також побачите посилання на те, що "глобали" є "злими".

Давайте зіткнемося з цим - будь-що, що не використовується належним чином, зловживається, не використовується, є злом. Це не обмежується будь-якою мовою, будь-якою концепцією кодування, будь-яким методом. Кожного разу, коли ви бачите, як хтось видає бланкетні висловлювання на зразок "X - це зло", біжіть від цієї статті. Швидше за все, що це продукт обмеженої точки зору - навіть якщо точка зору є результатом багаторічного досвіду в чомусь конкретному, - що, як правило, є результатом занадто багато роботи в заданому стилі / методі - типовому інтелектуальному консерватизмі.

Для цього можна навести нескінченні приклади, починаючи від «глобальних злих» до «іфрам - це зло». Ще близько 10 років тому, навіть пропонування використання рамки в будь-якій програмі було єресью. Потім приходить Facebook, iframes скрізь, і дивись, що сталося - iframes вже не такі злі.

Ще є люди, які вперто наполягають на тому, що вони «злі» - а іноді й з поважної причини - але, як бачите, є потреба, якщо рамки заповнюють цю потребу і працюють добре, і тому весь світ просто рухається далі.

Першочерговим надбанням програміста / кодера / програмного інженера є вільний, відкритий та гнучкий розум.


2
-1. Хоча я погоджуюся, що відкритий і гнучкий розум є обов'язковим активом для будь-якого розробника, але він не викуповує Singleton від антипатрійного. Вищенаведена відповідь містить стільки неточних тверджень та неправильних висновків щодо природи та наслідків Сінглтона, що я не можу не спростовувати це.
Гордон

-1. Мені довелося випробувати рамку з безліччю синглів з перших рук і автоматичне тестування неможливо. Я повинен вручну протестувати все за допомогою проб і помилок у браузері. Деякі помилки можна запобігти при перегляді коду (правопис, синтаксичні помилки), але функціональні помилки часто приховуються. Це тестування вимагає набагато більше часу, ніж одиничні тести. За допомогою модульних тестів я міг би сказати: Цей клас працює ізольовано, помилка повинна бути десь в іншому місці. Без налагодження нудно.
Джим Мартенс

Рамки повинні були мати вбудований журнал реєстрації та відстеження помилок. Крім того, клас, що працює належним чином ізольовано, також би працював належним чином у однотонній формі, коли його було застосовано до більш широкого застосування. Що означає, що в цьому випадку те, що порушується, був би іншим класом або функцією, яка взаємодіє з цим синглтоном. Це не відрізняється від звичайного відстеження помилок у великій програмі. Що само по собі досить складно без додатка, що має належну реєстрацію.
єдність100

Неточний. Тон одиночних тонів, безумовно, ЗЛИВ, адже це створює Тестування-ПЕКЛО. :-) Однак одна однотонність на додаток може бути хорошою. Наприклад: як уніфікована функція ведення журналу - для реалізації в усіх додатках (включаючи деякі застарілі).
Filip OvertoneSinger Rydlo

"Час, який може бути втрачено на тестування ..." Це дійсно погана практика та спосіб мислення. Усі ті застарілі програми там, де розроблено це, маючи на увазі, і підтримати їх стало неможливо, тому їх потрібно було переписати. Якщо тестів немає, час буде втрачено, коли буде розроблена нова функція і щось порушено в якійсь іншій частині системи. Час, загублений під час налагодження, час, який втрачають користувачі, які можуть правильно використовувати цю функцію, втрачається впевненість у програмі тощо
bogdancep

15

Багато хто вважає одиночні анти-зразками, оскільки вони справді просто прославлені глобальні змінні. На практиці існує відносно невелика кількість сценаріїв , в яких це необхідно для класу , щоб мати тільки один екземпляр; як правило , це тільки , що один екземпляр досить , в цьому випадку його реалізація , як одноточковий абсолютно непотрібний.

Щоб відповісти на запитання, ви маєте рацію, що одинаки тут надмірно вбиті. Проста змінна або функція зробить. Однак, кращим (більш надійним) підходом було б використання ін'єкцій залежності, щоб взагалі усунути потребу в глобальних змінних.


Але Singletons може дуже плавно деградувати на DI, статичні класи не можуть, що є реальною проблемою для статичних класів.
Білл К

@Bill: Дуже правда, але тоді я б виступав за підхід DI для початку, а не розпущених функцій чи статичних методів :)
Буде Вусден

У деяких мовах (наприклад, Java) статичні класи (або статичні методи класів) не можуть бути розширені. Таким чином ви створюєте потенційні проблеми (або в кращому випадку більше роботи) для майбутніх розробників. Тому деякі припускають, що статичних методів слід уникати, якщо у вас немає конкретної потреби.
Марво

8

У своєму прикладі ви маєте справу з однією частиною, здавалося б, незмінною інформацією. У цьому прикладі Singleton було б надмірним, і просто використання статичної функції в класі буде добре.

Більше думок: у вас може виникнути випадок впровадження моделей заради шаблонів, і ваша кишка говорить вам "ні, вам не потрібно" з причин, які ви прописали.

АЛЕ: Ми не маємо уявлення про розмір та масштаб вашого проекту. Якщо це простий код, можливо, викиньте його, який, мабуть, не знадобиться змінювати, то так, продовжуйте користуватися статичними елементами. Але якщо ви думаєте, що ваш проект може потребувати масштабування або бути готовим до кодування технічного обслуговування вниз по дорозі, так, так, можливо, ви захочете використовувати шаблон Singleton.


1
Нічого собі, просто неправильно. Вся суть різниці (відповідь на запитання) полягає в тому, наскільки складніше пізніше виправити свій код, щоб додати другий екземпляр. Набагато складніше це зробити, якщо ти використовував статичні методи. Це як би сказати, що "Глобали прекрасні за ваших обмежених умов", коли вся проблема з Глобалом полягає в тому, що умови змінюються.
Білл К

@Bill K: Я згоден з вами, і я би використав синглтон, якби взагалі була якась складність. Але я намагався відповісти на це питання з точки зору ОП і подумав, ну так, так, я думаю, що в цьому дуже обмеженому випадку це надмірність. Звичайно, я ігнорував питання архітектури чи масштабованості та безліч інших міркувань. Чи повинен я включити це як застереження у свою відповідь, условно пояснюючи, чому хтось завжди повинен використовувати одиноку ... що, безумовно, спричинило б прихильність інших?
Пол Сасик

5

По-перше, я просто хочу сказати, що я не знаходжу багато користі для моделі Singleton. Чому б хотілося ретельно зберігати один об’єкт у всій програмі? Особливо для баз даних, що робити, якщо я хочу підключитися до іншого сервера баз даних? Я маю щоразу відключатись та підключатись знову? Все одно ...

Існує кілька недоліків використання глобальних програм у додатку (саме це робить традиційне використання шаблону Singleton):

  • Складно провести одиничний тест
  • Проблеми з ін'єкцією залежності
  • Може створювати проблеми із блокуванням (багатопотокова програма)

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

Ви можете обмежити кількість примірників, які може мати клас, не використовуючи традиційний getInstanceметод:

class Single {

    static private $_instance = false;

    public function __construct() {
        if (self::$_instance)
           throw new RuntimeException('An instance of '.__CLASS__.' already exists');

        self::$_instance = true;
    }

    private function __clone() {
        throw new RuntimeException('Cannot clone a singleton class');
    }

    public function __destruct() {
        self::$_instance = false;
    }

}

$a = new Single;
$b = new Single; // error
$b = clone($a); // error
unset($a);
$b = new Single; // works

Це допоможе в першу чергу згаданими вище пунктами: тестування одиниць та введення залежності; при цьому переконуючись, що у вашій програмі існує один екземпляр класу. Наприклад, ви можете просто передати отриманий об'єкт вашим моделям (MVC-шаблон) для їх використання.


5

Подумайте, чим ваше рішення відрізняється від рішення, представленого в документах PHP. Насправді, існує лише одна «невелика» різниця: ваше рішення надає абонентам getter PDOекземпляр, тоді як той, який знаходиться в документах, надає виклику Database::singletonз Databaseекземпляром (вони потім використовують getter для цього, щоб отримати PDOекземпляр).

Тож до якого висновку ми дійшли?

  • У коді документації абоненти отримують Databaseекземпляр. DatabaseКлас може виставити (насправді, він повинен виставити , якщо ви збираєтеся на всі ці проблеми) багатшими або більш високого рівня , інтерфейс , ніж PDOоб'єкт він загортає.
  • Якщо ви зміните свою реалізацію, щоб повернути інший (багатший) тип, ніж PDOдва, то дві реалізації рівносильні. Виконання вручну не може бути корисним.

З практичної сторони, Сінглтон - досить суперечлива модель. Це в основному тому, що:

  • Це зловживати. Новачки-програмісти роблять синглтон набагато простіше, ніж обробляють інші моделі. Потім вони продовжують застосовувати свої нові знання всюди, навіть якщо проблему можна вирішити краще без Singleton (коли ти тримаєш молоток, все виглядає як цвях).
  • Залежно від мови програмування, реалізація Singleton герметичним, непротікаючим способом може виявитися титанічним завданням (особливо, якщо у нас є розширені сценарії: синглтон залежно від іншого сингтона, синглтони, які можна знищити та знову створити тощо) ). Постарайтеся пошукати "остаточну" реалізацію Singleton в C ++, я зважусь на вас (я володію новаторським "Сучасним дизайном" C ++ "Андрія Олександреску", який документує велику безладу).
  • Він накладає додаткове навантаження як при кодуванні Singleton, так і при написанні коду для доступу до нього, робоче навантаження якого ви можете виконувати, не дотримуючись кількох самостійно обмежених обмежень щодо того, що ви намагаєтеся зробити зі змінними вашої програми.

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


2

Ваше тлумачення правильне. Сінглтони мають своє місце, але надмірно використовуються. Часто доступ до функцій статичних членів є достатнім (особливо, коли вам не потрібно контролювати час будівництва будь-яким способом). Краще, ви можете просто розмістити кілька вільних функцій та змінних у просторі імен.


2

При програмуванні немає "правильного" і "неправильного"; є "хороша практика" та "погана практика".

Синглтонтони, як правило, створюються як клас, який потрібно використовувати повторно. Вони повинні бути створені таким чином, щоб програміст випадково не заповнив два екземпляри під час п'яного кодування опівночі.

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

не завжди є поганою практикою мати глобальні об'єкти. Якщо ви знаєте, що ви будете використовувати його у всьому світі / скрізь / постійно, це може бути одним з небагатьох винятків. Однак загалом глобалісти вважаються «поганою практикою» так само, gotoяк і поганою.


2

Я взагалі не бачу в цьому сенсу. Якщо ви реалізували клас таким чином, що рядок з'єднання приймався за параметр конструктору і підтримував список об'єктів PDO (по одному для кожної унікальної рядки з'єднання), можливо, буде якась користь, але реалізація сингтона в цей приклад здається безглуздою вправою.


1

Ви нічого не пропускаєте, наскільки я бачу. Приклад досить хибний. Було б важливо, якби клас одиночних мав деякі нестатичні змінні екземпляра.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.