ООП PHP
Шаблоны проектирования
Шаблоны проектирования: Шаблоны проектирования
Шаблоны проектирования
Шаблоны проектирования - это инструкции, руководства для решения каких-то конкретных проблем
Рассмотрим шаблон проектирования (паттерн) - Singleton (одиночка), как самый простой для понимания и который можно использовать на практике очень часто.
Пример: Db Connector для подключения к базе данных.
Допустим, нам необходима работа с базой данных, соотетственно, есть класс для работы с базой данных, а от класса можно создавать объекты. И в конструкторе, когда мы работаем с классом Db, мы можем устанавливать соединение с базой данных. В этом случае, когда мы создадим два объекта данного класса, произойдет два соединения с базой данных. Поэтому встает задача как-то контролировать тот факт - создан ли объект класса Db и соответственно, не открыто ли было уже соединение с базой данных. Для того, чтобы это контролировать, как раз и существует паттерн Singleton, который не позволяет создать более одного объекта:
- если объект создан, тогда будет возвращен объект,
- если не создан, тогда объект данного класса будет создан и возвращен.
Суть паттерна заключается в том, что конструктор создается здесь приватным, а это значит, что от этого класса мы не сможем создать объект.
В классе А создадим приватный конструктор:
Файл A.php
-- файл A.php --
<?php
namespace ;
class
{
// закрытый конструктор означает, что от этого класса мы не сможем создать объект
private function ()
{
}
}
?>
Если мы попытаемся создать объект класса A:
$a = new \app\A();
- получим ошибку: попытка вызова конструктора от класса А, который является приватным.
А приватные свойства и методы из вне не видны.
Для того, чтобы создать объект этого класса, существует закрытое (приватное) свойство $instance в котором и будет хранится объект данного класса. И создается метод, который часто называют getInstance(), он публичный и он статичный :
public static function getInstance()
{
if (null === static::$instance)
{
static::$instance = new static();
}
return static::$instance;
}
- здесь мы проверяем:
if (null === static::$instance)
- если у нас свойство $instance - пусто (в нем нет никакого объекта), тогда мы в это свойство запишем это самый объект:
static::$instance = new static();- создадим объект самого себя
(здесь используется static - он ссылается на сам себя, аналог - self)
return static::$instance;
- возвращаем объект. При последующему обращении к этому методу проверка уже не выполниться и мы сразу возвращаем этот объект.
Реализуем этот простейший паттерн в коде.
Файл A.php
-- файл A.php --
<?php
namespace ;
class
{
// создадим закрытое статичное свойство $instanses
private static $instances ;
// создаем закрытый конструктор
private function ()
{
}
// создаем публичный статичный метод , что-бы к нему можно было обратиться из вне
public static function ()
{
// проверяем:
// если объект текущего класса в нем не записан
if(self::$instances === null)
{
// тогда мы это запишем:
self::$instances = new self();
// - здесь мы обращаемся к текущему классу и содаем объект
// этого класса new self(), и записываем его в
// приватное свойство $instances
// То есть, мы в свойство $instances записываем объект new self() и ---
}
// --- возвращаем его
return self::$instances;
}
}
?>
В индексном файле мы не можем создать объект через new, но мы можем обратиться к классу А и вызвать метод getInstance(). Создадим и распечатаем объекты $a1 и $a2:
...
...
...
$a1 = \app\A::getInstance();
$a2 = \app\A::getInstance();
var_dump($a1);
echo '<br>';
var_dump($a2);
Выведет:
object(app\A)[4]
object(app\A)[4]
- получаем, что ($a1) и ($a2) - один и тот-же объект класса А (с номером - 4)
(С использованием Singleton у нас получается один и тот же объект)
Singleton можно использовать не только для класса Db, но и для других классов, от которых мы хотим создавать не более одного объекта. И соответственно, для всех зтих классов нам достаточно определить свойство $instances, приватный конструктор и метод getInstance().
Если мы в классе B продублируем код и в индексном файле создадим и распечатаем дополнительно объекты $b1 и $b2:
...
...
...
$b1 = \app\B::getInstance();
$b2 = \app\B::getInstance();
var_dump($b1);
echo '<br>';
var_dump($b2);
- то получим:
object(app\A)[4] - два одинаковых объекта класса А
object(app\A)[4]
object(app\B)[5] - и два объекта одинаковых класса B
object(app\B)[5]
Чтобы избежать дублирование кода используем трейты (traits).
Создадим в папке traits трейт TSingleton.
Файл TSingleton.php
-- файл TSingleton.php --
<?php
namespace \ ;
trait
{
// создадим закрытое статичное свойство $instanses
private static $instances;
// создаем закрытый конструктор
private function ()
{
}
// создаем публичный статичный метод , что-бы к нему можно было обратиться из вне
public static function ()
{
// проверяем:
// если объект текущего класса в нем не записан
if(self::$instances === null)
{
// тогда мы это запишем:
self::$instances = new self();
// - мы обращаемся к текущему классу и содаем объект
// этого класса new self(), и записываем его в
// приватное свойство $instances
// То есть, мы в свойство $instances записываем объект new self() и ---
}
// --- возвращаем его
return self::$instances;
}
}
?>
В классе А используем - use TSingleton
Файл A.php
-- файл A.php --
<?php
namespace ;
use \ \ \ ; // подключаем TSingleton
class
{
use ;
}
?>
Тоже самое делаем и для класса B
Файл B.php
-- файл B.php --
<?php
namespace ;
class
{
use \ \ \ ; // путь подключаем здесь
}
?>
Файл index.php:
-- файл index.php --
<?php
use \{ , };
use \ \{ , };
(-1);
require_once . '/vendor/autoload.php';
function ($data)
{
echo '<pre>' . ($data, 1 ) . '</pre>';
}
function ($product)
{
echo "<p>Предлагаем чехол для гаджета {$product -> ()} </p>";
}
$book = new ('Три мушкетера', 20, 1000);
$notebook = new ('Dell', 1000, 'Intel' );
// Шаблоны проектирования ---------------------------------------------
// пытаемся создать объект:
//$a = new \app\A();
// - вызовет ошибку: идет попытка вызова конструктора от класса А,
// который является приватным, а приватные методы и свойства из вне не видны
// мы не можем создать объект класса через оператор new, но
// теперь можно создать объект класса через вызов метода getInstance() класса A
$a1 = \ \ :: ();
$a2 = \ \ :: ();
($a1);
echo '<br>';
($a2);
// - получаем, что ($a1) и ($a2) - один и тот-же объект класса А (с номером - 4)
echo '<br>';
$b1 = \ \ :: ();
$b2 = \ \ :: ();
($b1);
echo '<br>';
($b2);
// получаем, что ($b1) и ($b2) - один и тот-же объект класса В (с номером - 5)
?>
Получим:
object(app\A)[4] - два одинаковых объекта класса А
object(app\A)[4]
object(app\B)[5] - и два объекта одинаковых класса B
object(app\B)[5]
Содержание папки 17 ("Шаблоны проектирования"):
Мы избежали дублирование кода, создав трейт, который реализует паттерн Singleton, и подключив данный трейт в нужные классы, мы делаем эти классы реализующими паттерн Singleton.
Наверх Наверх