Skip to content

Latest commit

 

History

History
executable file
·
206 lines (129 loc) · 13.2 KB

27_Design_patterns,_Singletone.md

File metadata and controls

executable file
·
206 lines (129 loc) · 13.2 KB

27. Шаблоны проектирования, порождающий шаблон Singleton

Введение

Сегодня мы начинаем довольно сложную тему шаблонов проектирования (Design patterns).

Design patterns Everywhere мем

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

Квадратное уравнение

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

Корни уравнения через дискриминант

По такому же принципу работают и шаблоны проектироания.

В 1991 году Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес (John Vlissides) публикуют книгу Design Patterns — Elements of Reusable Object-Oriented Software.

Банда четырех мем

В этой книге описаны 23 шаблона проектирования. Также команда авторов этой книги известна общественности под названием «Банда четырёх» (англ. Gang of Four, часто сокращается до GoF). До появления этой книги и предшествовавших ей работ ее авторов никто не формализовал и не использовал шаблоны проектирования. После выхода книги тема стала очень популярной.

Виды шаблонов

Основные виды шаблонов проектирования:

  • порождающие
  • структурные
  • поведенческие
  • архитектурные

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

Есть 6 классических порождающих шаблонов проектирования:

  • Простая фабрика
  • Фабричный метод
  • Абстрактная фабрика
  • Строитель
  • Прототип
  • Одиночка

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

Есть 7 классических структурных шаблонов проектирования:

  • Адаптер
  • Мост
  • Компоновщик
  • Декоратор
  • Фасад
  • Приспособленец
  • Заместитель

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

Десятка классических поведенческих шаблонов проектирования:

  • Цепочка ответственности
  • Команда
  • Итератор
  • Посредник
  • Хранитель
  • Наблюдатель
  • Посетитель
  • Стратегия
  • Состояние
  • Шаблонный метод

Выше перечислены лишь 23 классических шаблона проектирования от "Банды четырех". Помимо этих шаблонов есть масса других, в том числе как этих трех видов, так и архитектурные, а могут быть и еще каких-то дополнительных видов.

проектирование мем

В этом уроке мы рассмотрим два довольно простых, но важных и интересных порождающих шаблона: Одиночка (Singleton) и и Простая фабрика (Simple Fabric)

###Шаблон проектирования Singleton

Одним из самых известных и популярных шаблонов проектирования в целом является шаблон Singleton.

Синглтон мем

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

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

Для начала, создадим класс, который будет подключаться к БД:

<?php

class DB {

  function __construct(){
    $this->con = new mysqli("127.0.01", "root", "12345", "books");
  }

}

$db = new DB();
print_r($db->con->query("SELECT title FROM books")->fetch_all());

Итак, у нас есть класс, который в конструкторе подключается к БД, подключение работает и позволяет выполнять запросы к БД.

Ничего на данный момент не мешает нам создать второй объект и выполнить второе подключение к той же БД. Необходимо каким-то образом запретить создавать объекты этого класса. Применим наши знания принципов ООП и магических методов, а имено: ограничим доступ к конструктору объекта, добавив ему спецификатор доступа private.

После такого изменения мы не сможем создавать новые объекты. Естественно, мы так же потеряем возможность создавать тот самый единственный способ.

Единственный способ создавать объект (при помощи ключего слова new) - создавать объект внутри класса, т.е. в рамках какого-то метода. Но. Обычные методы класса мы запускаем только посредством объекта класса, который мы как раз и не можем создать.

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

<?php
class DB {

  private function __construct(){
    $this->con = new mysqli("127.0.01", "root", "12345", "books");
  }

  static public function getConnect(){
    return (new self())->con;
  }

}

$con = DB::getConnect();
print_r($con->query("SELECT title FROM books")->fetch_all());

...отлично. Применили на практике знания о статике, но мы все равно имеем возможность создавать несколько объектов, просто более сложным путем. Но тут уже все проще, нам достаточно каким-то образом проверять, создавали ли мы объект, и не позволять создавать новые.

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

class DB {

  static $obj;

  private function __construct(){
    $this->con = new mysqli("127.0.01", "root", "12345", "books");
  }

  static public function getConnect(){
    if(empty(self::$obj))
      self::$obj = new self();
    return self::$obj->con;
  }

}

$con = DB::getConnect();
print_r($con->query("SELECT title FROM books")->fetch_all());

Варианты хранить bool переменную или счетчик созданных объектов нам в данном случае не подходит, ведь наш метод должен не только не позволять создавать новые объекты, но и как-то позволять работать со старым. Будем сохранять этот объект. Мы практически завершили написание шаблона проектирования Singleton, остался только один момент - закрыть еще два возможных варианта создания объектов, а именно: десериализацию и клонирование:

<?php

class DB {

  static $obj;

  private function __clone(){}
  private function __wakeup(){}
  
  private function __construct(){
    $this->con = new mysqli("127.0.01", "root", "12345", "books");
  }

  static public function getConnect(){
    if(empty(self::$obj))
      self::$obj = new self();
    return self::$obj->con;
  }

}

$con = DB::getConnect();
print_r($con->query("SELECT title FROM books")->fetch_all());

Мы реализовали самый известный, простой и популярный шаблон проектирования Singleton. На всякий случай имеет смысл прочесть статью на тему минусов его применения на сайте troger.ru.

Домашнее задание

  1. Написать класс для работы с книгами в базе данных.
  2. Написать с нуля для него подключение к БД с использованием шаблона проектирования Singleton.
  3. Почитать про другие шаблоны проектирования как в "банде четырех", так и в других книгах (рекомендую книги авторов Мэтта Зандстры, Александра Швеца), почитать статьи по ссылкам:

Порождающие шаблоны

Структурные шаблоны

Поведенческие шаблоны