
Reg.ru: домены и хостинг
Крупнейший регистратор и хостинг-провайдер в России.
Более 2 миллионов доменных имен на обслуживании.
Продвижение, почта для домена, решения для бизнеса.
Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Бесплатный Курс "Практика HTML5 и CSS3"
Освойте бесплатно пошаговый видеокурс
по основам адаптивной верстки
на HTML5 и CSS3 с полного нуля.

Фреймворк Bootstrap: быстрая адаптивная вёрстка
Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.
Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.
Верстайте на заказ и получайте деньги.
*Наведите курсор мыши для приостановки прокрутки.
Шаблон проектирования «Наблюдатель»
В этой статье мы поговорим о шаблоне проектирования под названием "Наблюдатель". Наблюдатель - это некто, кто следит за вашей активностью и при необходимости имеет возможность предпринять определенные действия в зависимости от вашей активности.
Аналогичный принцип заложен и в работу этого шаблона проектирования.
Данный шаблон следует применять в случаях, когда у нас есть зависимость "один ко многим" и некий объект должен быть изменен, когда происходят изменения с любым из других объектов.
В Википедии по этому поводу написано следующее:
Шаблон проектирования "Наблюдатель" - это поведенческий шаблон проектирования. Также известен как «подчинённые» (Dependents), «издатель-подписчик» (Publisher-Subscriber). Создает механизм у класса, который позволяет получать экземпляру объекта этого класса оповещения от других объектов об изменении их состояния, тем самым наблюдая за ними.
Данный шаблон проектирования - ключевая составляющая популярного архитектурного паттерна model–view–controller (MVC).
Для демонстрации работы этого шаблона давайте рассмотрим пример приложения, которое показывает курсы различных валют относительно доллара США. Подразумевается, что приложение показывает цену и также обновляет ее через определенные интервалы времени.
Прежде, чем мы начнем, давайте определим основные обязанности главного класса приложения (который в данном примере будет "Наблюдателем"):
- Наблюдатель должен иметь возможность добавлять новые валюты.
- Наблюдатель должен показывать статус / значение каждой валюты.
Теперь давайте его реализуем:
interface Observer { public function addCurrency(Currency $currency); } class priceSimulator implements Observer { private $currencies; public function __construct() { $this->currencies = array(); } public function addCurrency(Currency $currency) { array_push($this->currencies, $currency); } public function updatePrice() { foreach ($this->currencies as $currency) { $currency->update(); } } }
Если вы посмотрите на код выше, то увидите, что он может выполнять те функции, которые мы на него возложили.
Наблюдатель готов. Что нам нужно сейчас, так это несколько разных валют, которые мы можем добавить, после чего мы двинемся дальше. Давайте реализуем классы для работы с валютами.
interface Currency { public function update(); public function getPrice(); } class Pound implements Currency { private $price; public function __construct($price) { $this->price = $price; echo "<p>Исходная цена фунта: {$price}</p>"; } public function update() { $this->price = $this->getPrice(); echo "<p>Обновленная цена фунта: {$this->price}</p>"; } public function getPrice() { return f_rand(0.65, 0.71); } } class Yen implements Currency { private $price; public function __construct($price) { $this->price = $price; echo "<p>Исходная цена йены: {$price}</p>"; } public function update() { $this->price = $this->getPrice(); echo "<p>Обновленная цена йены: {$this->price}</p>"; } public function getPrice() { return f_rand(120.52, 122.50); } }
Ок, теперь все готово для того, чтобы собрать все воедино и запустить нашего Наблюдателя.
Собираем код вместе:
interface Observer { public function addCurrency(Currency $currency); } class priceSimulator implements Observer { private $currencies; public function __construct() { $this->currencies = array(); } public function addCurrency(Currency $currency) { array_push($this->currencies, $currency); } public function updatePrice() { foreach ($this->currencies as $currency) { $currency->update(); } } } interface Currency { public function update(); public function getPrice(); } class Pound implements Currency { private $price; public function __construct($price) { $this->price = $price; echo "<p>Исходная цена фунта: {$price}</p>"; } public function update() { $this->price = $this->getPrice(); echo "<p>Обновленная цена фунта: {$this->price}</p>"; } public function getPrice() { return f_rand(0.65, 0.71); } } class Yen implements Currency { private $price; public function __construct($price) { $this->price = $price; echo "<p>Исходная цена йены: {$price}</p>"; } public function update() { $this->price = $this->getPrice(); echo "<p>Обновленная цена йены: {$this->price}</p>"; } public function getPrice() { return f_rand(120.52, 122.50); } } function f_rand($min=0,$max=1,$mul=1000000){ if ($min>$max) return false; return mt_rand($min*$mul,$max*$mul)/$mul; } $priceSimulator = new priceSimulator(); $currency1 = new Pound(0.60); $currency2 = new Yen(122); $priceSimulator->addCurrency($currency1); $priceSimulator->addCurrency($currency2); echo "<hr />"; $priceSimulator->updatePrice(); echo "<hr />"; $priceSimulator->updatePrice();
Выполнение данного кода даст следующий результат:
Исходная цена фунта: 0.6 Исходная цена йены: 122 ------------- Обновленная цена фунта: 0.65346 Обновленная цена йены: 121.287809 ------------- Обновленная цена фунта: 0.671269 Обновленная цена йены: 121.300605
Вы можете видеть, что в этом коде мы обновили цены для всех ранее созданных валют и вывели их на экран.
Теперь давайте подумаем, как можно добавлять новые валюты в приложение с минимальными его изменениями.
Данные изменения касаются лишь процесса регистрации (добавления) новой валюты в наше приложение. Таким образом, наш клиентский код остается нетронутым, когда он вызывает функцию обновления цены в приложении.
Добавление новой валюты:
class Euro implements Currency { private $price; public function __construct($price) { $this->price = $price; echo "<p>Исходная цена евро: {$price}</p>"; } public function update() { $this->price = $this->getPrice(); echo "<p>Обновленная цена евро: {$this->price}</p>"; } public function getPrice() { return f_rand(0.78, 0.85); } }
Добавить новую валюту было очень просто, и теперь нам осталось лишь заставить нашего Наблюдателя ее отслеживать:
$priceSimulator = new priceSimulator(); $currency1 = new Pound(0.60); $currency2 = new Yen(122); $currency3 = new Euro(122); $priceSimulator->addCurrency($currency1); $priceSimulator->addCurrency($currency2); $priceSimulator->addCurrency($currency3); echo "<hr />"; $priceSimulator->updatePrice(); echo "<hr />"; $priceSimulator->updatePrice();
Вывод
Состояние любого объекта в объектно-ориентированном программировании очень важно, ведь вся работа приложения строится на взаимодействии между объектами.
Часто бывает необходимо, чтобы часть объектов была оповещена, когда происходят изменения в других объектах. В этом случае на помощь приходит шаблон пректирования "Наблюдатель".
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также: